Merge pull request #108 from LabD/feature/segment-template-block
Adds an ifsegment template block
This commit is contained in:
@ -47,6 +47,8 @@ personalised content. To do this, you can go one of two directions.
|
|||||||
|
|
||||||
2. Create StreamField blocks only visible to your segment.
|
2. Create StreamField blocks only visible to your segment.
|
||||||
|
|
||||||
|
3. Create a template block only visible to your segment.
|
||||||
|
|
||||||
|
|
||||||
Method 1: Create a copy
|
Method 1: Create a copy
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
@ -59,13 +61,35 @@ You'll notice a new "Variants" dropdown button has appeared. Click the button
|
|||||||
and select the segment you'd like to create personalized content for.
|
and select the segment you'd like to create personalized content for.
|
||||||
|
|
||||||
Once you've selected the segment, a copy of the page will be created with a
|
Once you've selected the segment, a copy of the page will be created with a
|
||||||
title that includes the segment. Don't worry, you'r visitors won't be able to
|
title that includes the segment. Don't worry, your visitors won't be able to
|
||||||
see this title.
|
see this title.
|
||||||
|
|
||||||
You can change everything on this page you'd like. Visitors that are included in
|
You can change everything on this page you'd like. Visitors that are included in
|
||||||
your segment, will automatically see the new page you've created for them.
|
your segment, will automatically see the new page you've created for them.
|
||||||
|
|
||||||
|
|
||||||
Method 2: Create a block
|
Method 2: Create a StreamField block
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
|
||||||
|
Method 3: Create a template block
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
You can add a template block that only shows its contents to users of a
|
||||||
|
specific segment. This is done using the "segment" block.
|
||||||
|
|
||||||
|
When editing templates make sure to load the ``wagtail_personalisation_tags``
|
||||||
|
tags library in the template::
|
||||||
|
|
||||||
|
{% load wagtail_personalisation_tags %}
|
||||||
|
|
||||||
|
After that you can add a template block with the name of the segment you want
|
||||||
|
the content to show up for::
|
||||||
|
|
||||||
|
{% segment name="My Segment" %}
|
||||||
|
<p>Only users within "My Segment" see this!</p>
|
||||||
|
{% endsegment %}
|
||||||
|
|
||||||
|
The template block currently only supports one segment at a time. If you want
|
||||||
|
to target multiple segments you will have to make multiple blocks with the
|
||||||
|
same content.
|
||||||
|
@ -97,8 +97,11 @@ class SessionSegmentsAdapter(BaseSegmentsAdapter):
|
|||||||
:rtype: wagtail_personalisation.models.Segment or None
|
:rtype: wagtail_personalisation.models.Segment or None
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
try:
|
||||||
return next(item for item in self.request.session['segments']
|
return next(item for item in self.request.session['segments']
|
||||||
if item.id == segment_id)
|
if item['id'] == segment_id)
|
||||||
|
except StopIteration:
|
||||||
|
return None
|
||||||
|
|
||||||
def add(self, segment):
|
def add(self, segment):
|
||||||
"""Add a segment to the request session.
|
"""Add a segment to the request session.
|
||||||
|
@ -0,0 +1,58 @@
|
|||||||
|
from django import template
|
||||||
|
from django.template import TemplateSyntaxError
|
||||||
|
|
||||||
|
from django.utils.safestring import mark_safe
|
||||||
|
|
||||||
|
from wagtail_personalisation.models import Segment
|
||||||
|
from wagtail_personalisation.utils import parse_tag
|
||||||
|
|
||||||
|
register = template.Library()
|
||||||
|
|
||||||
|
|
||||||
|
def do_segment(parser, token):
|
||||||
|
"""Block that only shows content if user is in chosen segment."""
|
||||||
|
# Parse the tag
|
||||||
|
tag_name, _, kwargs = parse_tag(token, parser)
|
||||||
|
|
||||||
|
# If no segment is provided this block will raise an error
|
||||||
|
if set(kwargs.keys()) != {'name'}:
|
||||||
|
usage = '{% {tag_name} name="segmentname" %} ... {% end{tag_name} %}'.format(tag_name=tag_name)
|
||||||
|
raise TemplateSyntaxError("Usage: %s" % usage)
|
||||||
|
|
||||||
|
nodelist = parser.parse(('endsegment',))
|
||||||
|
parser.delete_first_token()
|
||||||
|
|
||||||
|
return SegmentNode(nodelist, name=kwargs['name'])
|
||||||
|
|
||||||
|
|
||||||
|
register.tag('segment', do_segment)
|
||||||
|
|
||||||
|
|
||||||
|
class SegmentNode(template.Node):
|
||||||
|
"""Node that only returns contents if user is in the segment.
|
||||||
|
|
||||||
|
This node checks if the chosen segment exists and if the
|
||||||
|
user has been segmented in the chosen segment.
|
||||||
|
If not it will return nothing
|
||||||
|
|
||||||
|
"""
|
||||||
|
def __init__(self, nodelist, name):
|
||||||
|
self.nodelist = nodelist
|
||||||
|
self.name = name
|
||||||
|
|
||||||
|
def render(self, context):
|
||||||
|
# Check if segment exists
|
||||||
|
name = self.name.resolve(context)
|
||||||
|
segment = Segment.objects.filter(name=name).first()
|
||||||
|
if not segment:
|
||||||
|
return ""
|
||||||
|
|
||||||
|
# Check if user has segment
|
||||||
|
user_segment = context['request'].segment_adapter.get_segment(segment_id=segment.pk)
|
||||||
|
if not user_segment:
|
||||||
|
return ""
|
||||||
|
|
||||||
|
content = self.nodelist.render(context)
|
||||||
|
content = mark_safe(content)
|
||||||
|
|
||||||
|
return content
|
@ -1,5 +1,6 @@
|
|||||||
import time
|
import time
|
||||||
|
|
||||||
|
from django.template.base import FilterExpression, kwarg_re
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
|
||||||
|
|
||||||
@ -58,3 +59,37 @@ def count_active_days(enable_date, disable_date):
|
|||||||
return delta.days
|
return delta.days
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def parse_tag(token, parser):
|
||||||
|
"""Parses template tag for name, arguments and keyword arguments.
|
||||||
|
|
||||||
|
:param token: Template token containing all the tag contents
|
||||||
|
:type token: django.template.base.Token
|
||||||
|
:param parser: Template parser
|
||||||
|
:type parser: django.template.base.Parser
|
||||||
|
:return: Tuple with tag name, arguments and keyword arguments
|
||||||
|
:rtype: tuple
|
||||||
|
|
||||||
|
"""
|
||||||
|
# Split the tag content into words, respecting quoted strings.
|
||||||
|
bits = token.split_contents()
|
||||||
|
|
||||||
|
# Pull out the tag name.
|
||||||
|
tag_name = bits.pop(0)
|
||||||
|
|
||||||
|
# Parse the rest of the args, and build FilterExpressions from them so that
|
||||||
|
# we can evaluate them later.
|
||||||
|
args = []
|
||||||
|
kwargs = {}
|
||||||
|
for bit in bits:
|
||||||
|
# Is this a kwarg or an arg?
|
||||||
|
match = kwarg_re.match(bit)
|
||||||
|
kwarg_format = match and match.group(1)
|
||||||
|
if kwarg_format:
|
||||||
|
key, value = match.groups()
|
||||||
|
kwargs[key] = FilterExpression(value, parser)
|
||||||
|
else:
|
||||||
|
args.append(FilterExpression(bit, parser))
|
||||||
|
|
||||||
|
return (tag_name, args, kwargs)
|
||||||
|
Reference in New Issue
Block a user