Add adapters.get_segment_adapter to set the segment adapter on the request
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
This commit is contained in:
committed by
Michael van Tellingen
parent
4158bafe58
commit
cc38634519
17
README.rst
17
README.rst
@ -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
|
||||
-------
|
||||
|
@ -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
|
||||
@ -10,6 +12,15 @@ from wagtail_personalisation.utils import create_segment_dictionary
|
||||
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
|
||||
@ -64,15 +75,8 @@ class BaseSegmentsAdapter(object):
|
||||
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):
|
||||
@ -166,3 +170,18 @@ class SessionSegmentsAdapter(BaseSegmentsAdapter):
|
||||
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
|
||||
|
@ -1,9 +0,0 @@
|
||||
from django.conf import settings
|
||||
from django.utils.module_loading import import_string
|
||||
|
||||
# Create a setting for the segments adapter to allow
|
||||
# overwriting of the provided adapter's functionality.
|
||||
segments_adapter = import_string(getattr(
|
||||
settings,
|
||||
'PERSONALISATION_SEGMENTS_ADAPTER',
|
||||
'wagtail_personalisation.adapters.SessionSegmentsAdapter'))()
|
@ -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
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ from wagtail.wagtailadmin.widgets import Button, ButtonWithDropdownFromHook
|
||||
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
|
||||
|
||||
@ -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')
|
||||
@ -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')
|
||||
|
Reference in New Issue
Block a user