7

moves all middleware logic to wagtail hook

This commit is contained in:
Boris Besemer
2016-12-06 12:17:50 +01:00
parent 1d227c28c6
commit 29b9ad695b
5 changed files with 78 additions and 120 deletions

View File

@ -21,14 +21,4 @@ Next, include the ``personalisation`` and ``wagtail.contrib.modeladmin`` app in
# ...
]
Last but not least, add ``personalisation.middleware.SegmentMiddleware`` to your project's ``MIDDLEWARE``:
.. code-block:: python
MIDDLEWARE = [
# ...
'personalisation.middleware.SegmentMiddleware',
# ...
]
Make sure that ``django.contrib.sessions.middleware.SessionMiddleware`` has been added in first, this is a prerequisite for this project.

View File

@ -1,89 +0,0 @@
import logging
import time
from django.urls import reverse
from personalisation.models import AbstractBaseRule, Segment
logger = logging.getLogger()
class SegmentMiddleware(object):
"""Middleware for testing and putting a user in a segment"""
def __init__(self, get_response=None):
self.get_response = get_response
def __call__(self, request):
reverse_urls = [reverse('admin:index'), reverse('wagtailadmin_home')]
if 'visit_count' not in request.session:
request.session['visit_count'] = []
request.session['segments'] = []
if any(request.path.startswith(item) for item in reverse_urls):
return self.get_response(request)
segments = Segment.objects.all().filter(status='enabled')
for segment in segments:
rules = AbstractBaseRule.__subclasses__()
segment_rules = []
for rule in rules:
queried_rules = rule.objects.filter(segment=segment)
for result in queried_rules:
segment_rules.append(result)
result = self.test_rules(segment_rules, request)
if result:
self.add_segment_to_user(segment, request)
response = self.get_response(request)
if request.session['segments']:
logger.info("User has been added to the following segments: {}".format(request.session['segments']))
return response
def test_rules(self, rules, request):
"""Test wether the user matches a segment's rules'"""
if len(rules) > 0:
for rule in rules:
result = rule.test_user(request)
# Debug
if result and rule.__class__.__name__ == "TimeRule":
print("User segmented. Time between {} and {}.".format(
rule.start_time,
rule.end_time))
if result and rule.__class__.__name__ == "ReferralRule":
print("User segmented. Referral matches {}.".format(rule.regex_string))
if result and rule.__class__.__name__ == "VisitCountRule":
print("User segmented. Visited {} {} {} times.".format(
rule.counted_page,
rule.operator,
rule.count))
if result is False:
return False
return True
return False
def add_segment_to_user(self, segment, request):
"""Save the segment in the user session"""
def check_if_segmented(segment):
"""Check if the user has been segmented"""
for seg in request.session['segments']:
if seg['encoded_name'] == segment.encoded_name():
return True
return False
if not check_if_segmented(segment):
segdict = {
"encoded_name": segment.encoded_name(),
"id": segment.pk,
"timestamp": int(time.time()),
}
request.session['segments'].append(segdict)

View File

@ -1,14 +1,18 @@
import time
import logging
from django.shortcuts import reverse
from django.conf.urls import include, url
from wagtail.contrib.modeladmin.options import ModelAdmin, modeladmin_register
from wagtail.contrib.modeladmin.views import IndexView
from wagtail.wagtailcore import hooks
from personalisation import admin_urls
from personalisation.models import PersonalisablePage, Segment
from personalisation.models import AbstractBaseRule, PersonalisablePage, Segment
from personalisation.utils import impersonate_other_page
logger = logging.getLogger()
@hooks.register('register_admin_urls')
def register_admin_urls():
@ -31,17 +35,13 @@ class SegmentModelAdmin(ModelAdmin):
form_view_extra_css = ['personalisation/segment/form.css']
inspect_view_enabled = True
modeladmin_register(SegmentModelAdmin)
modeladmin_register(SegmentModelAdmin)
@hooks.register('before_serve_page')
def set_visit_count(page, request, serve_args, serve_kwargs):
"""Update the users visit count before each page visit."""
# Update the segment visit count
for seg in request.session['segments']:
segment = Segment.objects.get(pk=seg['id'])
segment.visit_count = segment.visit_count + 1
segment.save()
if 'visit_count' not in request.session:
request.session['visit_count'] = []
# Update the page visit count
def create_new_counter(page, request):
@ -68,6 +68,76 @@ def set_visit_count(page, request, serve_args, serve_kwargs):
# No counters exist. Create a new counter with count value 1.
create_new_counter(page, request)
@hooks.register('before_serve_page')
def segment_user(page, request, serve_args, serve_kwargs):
request.session['segments'] = []
segments = Segment.objects.all().filter(status='enabled')
for segment in segments:
rules = AbstractBaseRule.__subclasses__()
segment_rules = []
for rule in rules:
queried_rules = rule.objects.filter(segment=segment)
for result in queried_rules:
segment_rules.append(result)
result = _test_rules(segment_rules, request)
if result:
_add_segment_to_user(segment, request)
if request.session['segments']:
logger.info("User has been added to the following segments: {}".format(request.session['segments']))
for seg in request.session['segments']:
segment = Segment.objects.get(pk=seg['id'])
segment.visit_count = segment.visit_count + 1
segment.save()
def _test_rules(rules, request):
"""Test wether the user matches a segment's rules'"""
if len(rules) > 0:
for rule in rules:
result = rule.test_user(request)
# Debug
if result and rule.__class__.__name__ == "TimeRule":
print("User segmented. Time between {} and {}.".format(
rule.start_time,
rule.end_time))
if result and rule.__class__.__name__ == "ReferralRule":
print("User segmented. Referral matches {}.".format(rule.regex_string))
if result and rule.__class__.__name__ == "VisitCountRule":
print("User segmented. Visited {} {} {} times.".format(
rule.counted_page,
rule.operator,
rule.count))
if result is False:
return False
return True
return False
def _add_segment_to_user(segment, request):
"""Save the segment in the user session"""
def check_if_segmented(segment):
"""Check if the user has been segmented"""
for seg in request.session['segments']:
if seg['encoded_name'] == segment.encoded_name():
return True
return False
if not check_if_segmented(segment):
segdict = {
"encoded_name": segment.encoded_name(),
"id": segment.pk,
"timestamp": int(time.time()),
}
request.session['segments'].append(segdict)
@hooks.register('before_serve_page')
def serve_variation(page, request, serve_args, serve_kwargs):
user_segments = []

View File

@ -52,7 +52,6 @@ MIDDLEWARE = (
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'wagtail.wagtailcore.middleware.SiteMiddleware',
'personalisation.middleware.SegmentMiddleware',
)
INSTALLED_APPS = (

View File

@ -195,15 +195,3 @@ class TestUserVisitCount(object):
client.get('/')
assert not any(item['path'] == '/doesntexist' for item in client.session['visit_count'])
def test_ignores_admin_visits(self, client):
client.get('/admin/')
assert not any(item['path'] == '/admin/' for item in client.session['visit_count'])
client.get('/django-admin/')
assert not any(item['path'] == '/django-admin/' for item in client.session['visit_count'])
assert client.session['visit_count'] == []