7

Update to use a post_init signal to populate the segment

This commit is contained in:
Todd Dembrey
2017-10-20 17:33:47 +01:00
parent 0d2834a55f
commit c6ff2801c5
3 changed files with 54 additions and 14 deletions

View File

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-10-20 16:26
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('wagtail_personalisation', '0013_add_dynamic_static_to_segment'),
]
operations = [
migrations.AddField(
model_name='segment',
name='frozen',
field=models.BooleanField(default=False),
),
]

View File

@ -9,6 +9,7 @@ from django.contrib.auth.models import AnonymousUser
from django.contrib.sessions.models import Session from django.contrib.sessions.models import Session
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.db import models, transaction from django.db import models, transaction
from django.dispatch import receiver
from django.template.defaultfilters import slugify from django.template.defaultfilters import slugify
from django.test.client import RequestFactory from django.test.client import RequestFactory
from django.utils import timezone from django.utils import timezone
@ -98,6 +99,7 @@ class Segment(ClusterableModel):
) )
) )
sessions = models.ManyToManyField(Session) sessions = models.ManyToManyField(Session)
frozen = models.BooleanField(default=False)
objects = SegmentQuerySet.as_manager() objects = SegmentQuerySet.as_manager()
@ -149,6 +151,12 @@ class Segment(ClusterableModel):
def is_full(self): def is_full(self):
return self.sessions.count() >= self.count return self.sessions.count() >= self.count
@property
def can_populate(self):
return (
self.id and self.is_static and not self.frozen and self.is_consistent
)
def encoded_name(self): def encoded_name(self):
"""Return a string with a slug for the segment.""" """Return a string with a slug for the segment."""
return slugify(self.name.lower()) return slugify(self.name.lower())
@ -185,22 +193,28 @@ class Segment(ClusterableModel):
if save: if save:
self.save() self.save()
def save(self, *args, **kwargs):
super(Segment, self).save(*args, **kwargs)
if self.is_static: @receiver(models.signals.post_init, sender=Segment)
request = RequestFactory().get('/') def populate_sessions_first_time(sender, **kwargs):
instance = kwargs.pop('instance', None)
if instance.can_populate:
request = RequestFactory().get('/')
for session in Session.objects.filter( for session in Session.objects.filter(
expire_date__gt=timezone.now(), expire_date__gt=timezone.now(),
).iterator(): ).iterator():
session_data = session.get_decoded() session_data = session.get_decoded()
user = user_from_data(session_data.get('_auth_id')) user = user_from_data(session_data.get('_auth_id'))
request.user = user request.user = user
request.session = SessionStore(session_key=session.session_key) request.session = SessionStore(session_key=session.session_key)
all_pass = all(rule.test_user(request) for rule in self.get_rules() if rule.static) all_pass = all(rule.test_user(request) for rule in instance.get_rules() if rule.static)
if not self.is_consistent and all_pass: if all_pass:
self.sessions.add(session) instance.sessions.add(session.session_key)
models.signals.post_init.disconnect(populate_sessions_first_time, sender=sender)
instance.frozen = True
instance.save()
models.signals.post_init.connect(populate_sessions_first_time, sender=sender)
class PersonalisablePageMetadata(ClusterableModel): class PersonalisablePageMetadata(ClusterableModel):

View File

@ -20,6 +20,9 @@ def test_session_added_to_static_segment_at_creation(rf, site, client):
VisitCountRule.objects.create(counted_page=site.root_page, segment=segment) VisitCountRule.objects.create(counted_page=site.root_page, segment=segment)
segment.save() segment.save()
# We need to trigger the post init
segment = Segment.objects.get(id=segment.id)
assert session.session_key in segment.sessions.values_list('session_key', flat=True) assert session.session_key in segment.sessions.values_list('session_key', flat=True)
@ -38,6 +41,9 @@ def test_mixed_static_dynamic_session_doesnt_generate_at_creation(rf, site, clie
) )
segment.save() segment.save()
# We need to trigger the post init
segment = Segment.objects.get(id=segment.id)
assert not segment.sessions.all() assert not segment.sessions.all()