Skip to content

Commit

Permalink
Add adapters.get_segment_adapter to set the segment adapter on the re…
Browse files Browse the repository at this point in the history
…quest

object.

Previously the segment adapter was set globally with the request as
attribute. This causes thread safety issues. Instead we now initialise
the segment adapter for each request and set it as attribute
  • Loading branch information
mvantellingen committed May 31, 2017
1 parent 4158baf commit cc38634
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 31 deletions.
17 changes: 16 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,22 @@ Next, include the ``wagtail_personalisation`` and
]
Make sure that ``django.contrib.sessions.middleware.SessionMiddleware`` has
been added in first.
been added in first, this is a prerequisite for this project.


Changing segments adapter
-------------------------
To change the segments adapter, first make a new one based on the
``BaseSegmentsAdapter``

.. code-block:: python
class YourSegmentsAdapter(BaseSegmentsAdapter):
# Add your own logic here
Add the ``PERSONALISATION_SEGMENTS_ADAPTER`` setting to your settings.py and
choose your own adapter.


Sandbox
-------
Expand Down
37 changes: 28 additions & 9 deletions src/wagtail_personalisation/adapters.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from __future__ import absolute_import, unicode_literals

from django.conf import settings
from django.db.models import F
from django.utils.module_loading import import_string

from wagtail_personalisation.models import Segment
from wagtail_personalisation.rules import AbstractBaseRule
Expand All @@ -10,6 +12,15 @@
class BaseSegmentsAdapter(object):
"""Base segments adapter."""

def __init__(self, request):
"""Prepare the request session for segment storage.
:param request: The http request
:type request: django.http.HttpRequest
"""
self.request = request

def setup(self):
"""Prepare the adapter for segment storage."""
return None
Expand Down Expand Up @@ -64,15 +75,8 @@ class Meta:
class SessionSegmentsAdapter(BaseSegmentsAdapter):
"""Segment adapter that uses Django's session backend."""

def setup(self, request):
"""Prepare the request session for segment storage.
:param request: The http request
:type request: django.http.HttpRequest
"""
self.request = request

def __init__(self, request):
super(SessionSegmentsAdapter, self).__init__(request)
self.request.session.setdefault('segments', [])

def get_all_segments(self):
Expand Down Expand Up @@ -166,3 +170,18 @@ def refresh(self):
self.request.session['segments'] = new_segments

self.update_visit_count()


SEGMENT_ADAPTER_CLASS = import_string(getattr(
settings,
'PERSONALISATION_SEGMENTS_ADAPTER',
'wagtail_personalisation.adapters.SessionSegmentsAdapter'))


def get_segment_adapter(request):
"""Return the Segment Adapter for the given request"""
try:
return request.segment_adapter
except AttributeError:
request.segment_adapter = SEGMENT_ADAPTER_CLASS(request)
return request.segment_adapter
9 changes: 0 additions & 9 deletions src/wagtail_personalisation/app_settings.py

This file was deleted.

18 changes: 10 additions & 8 deletions src/wagtail_personalisation/templatetags/datalayer_tags.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
from django.template import Library

from wagtail_personalisation.app_settings import segments_adapter
from wagtail_personalisation.adapters import get_segment_adapter

register = Library()


@register.inclusion_tag('wagtail_personalisation/tags/datalayer.html')
def render_datalayer():
@register.inclusion_tag('wagtail_personalisation/tags/datalayer.html', takes_context=True)
def render_datalayer(context):
"""Render the sessions active segments in a data layer script tag."""
segments = segments_adapter.get_all_segments()
segment_names = [item['encoded_name'] for item in segments]
request = context.get('request')
if request:
segments = get_segment_adapter(request).get_all_segments()
segment_names = [item['encoded_name'] for item in segments]

return {
'segments': segment_names
}
return {
'segments': segment_names
}
9 changes: 5 additions & 4 deletions src/wagtail_personalisation/wagtail_hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from wagtail.wagtailcore import hooks

from wagtail_personalisation import admin_urls
from wagtail_personalisation.app_settings import segments_adapter
from wagtail_personalisation.adapters import get_segment_adapter
from wagtail_personalisation.models import PersonalisablePage, Segment
from wagtail_personalisation.utils import impersonate_other_page

Expand Down Expand Up @@ -87,8 +87,8 @@ def segment_user(page, request, serve_args, serve_kwargs):
:type request: django.http.HttpRequest
"""
segments_adapter.setup(request)
segments_adapter.refresh()
adapter = get_segment_adapter(request)
adapter.refresh()


@hooks.register('before_serve_page')
Expand All @@ -105,8 +105,9 @@ def serve_variation(page, request, serve_args, serve_kwargs):
"""
user_segments = []
adapter = get_segment_adapter(request)

for segment in segments_adapter.get_all_segments():
for segment in adapter.get_all_segments():
try:
user_segment = Segment.objects.get(pk=segment['id'],
status='enabled')
Expand Down

0 comments on commit cc38634

Please sign in to comment.