7

Inline rules in the model admin

This commit is contained in:
Jasper Berghoef
2016-11-17 12:33:43 +01:00
parent 7ec039905d
commit 856992f987
4 changed files with 104 additions and 78 deletions

View File

@@ -0,0 +1,39 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.3 on 2016-11-17 11:01
from __future__ import unicode_literals
from django.db import migrations
import django.db.models.deletion
import modelcluster.fields
class Migration(migrations.Migration):
dependencies = [
('personalisation', '0025_auto_20161115_1310'),
]
operations = [
migrations.RemoveField(
model_name='abstractbaserule',
name='segment',
),
migrations.AddField(
model_name='referralrule',
name='segment',
field=modelcluster.fields.ParentalKey(default='', on_delete=django.db.models.deletion.CASCADE, related_name='referral_rules', to='personalisation.Segment'),
preserve_default=False,
),
migrations.AddField(
model_name='timerule',
name='segment',
field=modelcluster.fields.ParentalKey(default='', on_delete=django.db.models.deletion.CASCADE, related_name='time_rules', to='personalisation.Segment'),
preserve_default=False,
),
migrations.AddField(
model_name='visitcountrule',
name='segment',
field=modelcluster.fields.ParentalKey(default='', on_delete=django.db.models.deletion.CASCADE, related_name='visit_count_rules', to='personalisation.Segment'),
preserve_default=False,
),
]

View File

@@ -12,67 +12,21 @@ from django.utils.functional import cached_property
from django.utils.translation import ugettext_lazy as _
from modelcluster.fields import ParentalKey
from modelcluster.models import ClusterableModel
from polymorphic.models import PolymorphicModel
from wagtail.utils.decorators import cached_classmethod
from wagtail.wagtailadmin.edit_handlers import (
FieldPanel, MultiFieldPanel, ObjectList, PageChooserPanel, TabbedInterface)
from wagtail.wagtailadmin.edit_handlers import (FieldPanel, FieldRowPanel,
InlinePanel, MultiFieldPanel,
ObjectList, PageChooserPanel,
TabbedInterface)
from wagtail.wagtailadmin.forms import WagtailAdminPageForm
from wagtail.wagtailcore.models import Page
from personalisation.edit_handlers import ReadOnlyWidget
from polymorphic.models import PolymorphicModel
@python_2_unicode_compatible
class Segment(ClusterableModel):
"""Model for a new segment"""
name = models.CharField(max_length=255)
create_date = models.DateTimeField(auto_now_add=True)
edit_date = models.DateTimeField(auto_now=True)
enable_date = models.DateTimeField(null=True, editable=False)
disable_date = models.DateTimeField(null=True, editable=False)
visit_count = models.PositiveIntegerField(default=0, editable=False)
STATUS_CHOICES = (
('enabled', 'Enabled'),
('disabled', 'Disabled'),
)
status = models.CharField(max_length=20, choices=STATUS_CHOICES, default="enabled")
panels = [
FieldPanel('name'),
FieldPanel('status'),
]
def __str__(self):
return self.name
def encoded_name(self):
"""Returns a string with a slug for the segment"""
return slugify(self.name.lower())
def check_status_change(sender, instance, *args, **kwargs):
"""Check if the status has changed. Alter dates accordingly."""
try:
original_status = sender.objects.get(pk=instance.id).status
except sender.DoesNotExist:
original_status = ""
if original_status != instance.status:
if instance.status == "enabled":
instance.enable_date = datetime.now()
instance.visit_count = 0
return instance
if instance.status == "disabled":
instance.disable_date = datetime.now()
pre_save.connect(check_status_change, sender=Segment)
@python_2_unicode_compatible
class AbstractBaseRule(PolymorphicModel):
"""Base for creating rules to segment users with"""
segment = ParentalKey('Segment', related_name="rules")
def test_user(self, request):
"""Test if the user matches this rule"""
return True
@@ -84,12 +38,15 @@ class AbstractBaseRule(PolymorphicModel):
@python_2_unicode_compatible
class TimeRule(AbstractBaseRule):
"""Time rule to segment users based on a start and end time"""
segment = ParentalKey('Segment', related_name="time_rules")
start_time = models.TimeField(_("Starting time"))
end_time = models.TimeField(_("Ending time"))
panels = [
FieldRowPanel([
FieldPanel('start_time'),
FieldPanel('end_time'),
]),
]
def __init__(self, *args, **kwargs):
@@ -113,6 +70,7 @@ class TimeRule(AbstractBaseRule):
@python_2_unicode_compatible
class ReferralRule(AbstractBaseRule):
"""Referral rule to segment users based on a regex test"""
segment = ParentalKey('Segment', related_name="referral_rules")
regex_string = models.TextField(_("Regex string to match the referer with"))
panels = [
@@ -138,6 +96,7 @@ class ReferralRule(AbstractBaseRule):
@python_2_unicode_compatible
class VisitCountRule(AbstractBaseRule):
"""Visit count rule to segment users based on amount of visits"""
segment = ParentalKey('Segment', related_name="visit_count_rules")
OPERATOR_CHOICES = (
('more_than', 'More than'),
('less_than', 'Less than'),
@@ -154,9 +113,11 @@ class VisitCountRule(AbstractBaseRule):
)
panels = [
PageChooserPanel('counted_page'),
FieldRowPanel([
FieldPanel('operator'),
FieldPanel('count'),
PageChooserPanel('counted_page'),
]),
]
def __init__(self, *args, **kwargs):
@@ -194,6 +155,55 @@ class VisitCountRule(AbstractBaseRule):
return '{} {}'.format(operator_display, self.count)
@python_2_unicode_compatible
class Segment(ClusterableModel):
"""Model for a new segment"""
name = models.CharField(max_length=255)
create_date = models.DateTimeField(auto_now_add=True)
edit_date = models.DateTimeField(auto_now=True)
enable_date = models.DateTimeField(null=True, editable=False)
disable_date = models.DateTimeField(null=True, editable=False)
visit_count = models.PositiveIntegerField(default=0, editable=False)
STATUS_CHOICES = (
('enabled', 'Enabled'),
('disabled', 'Disabled'),
)
status = models.CharField(max_length=20, choices=STATUS_CHOICES, default="enabled")
panels = [
FieldPanel('name'),
FieldPanel('status'),
InlinePanel('time_rules', label="Time rule", min_num=None, max_num=1),
InlinePanel('referral_rules', label="Referral rule", min_num=None, max_num=1),
InlinePanel('visit_count_rules', label="Visit count rule", min_num=None, max_num=1),
]
def __str__(self):
return self.name
def encoded_name(self):
"""Returns a string with a slug for the segment"""
return slugify(self.name.lower())
def check_status_change(sender, instance, *args, **kwargs):
"""Check if the status has changed. Alter dates accordingly."""
try:
original_status = sender.objects.get(pk=instance.id).status
except sender.DoesNotExist:
original_status = ""
if original_status != instance.status:
if instance.status == "enabled":
instance.enable_date = datetime.now()
instance.visit_count = 0
return instance
if instance.status == "disabled":
instance.disable_date = datetime.now()
pre_save.connect(check_status_change, sender=Segment)
class AdminPersonalisablePageForm(WagtailAdminPageForm):
def __init__(self, *args, **kwargs):
super(AdminPersonalisablePageForm, self).__init__(*args, **kwargs)

View File

@@ -14,19 +14,6 @@
{% block form %}
{{ edit_handler.render_form_content }}
{% for form in additional_forms %}
<li class="object">
<h2>
<label for="{{ form.title }}">{{ form.title }}</label>
</h2>
<fieldset class="">
<p>{{ form.description }}</p>
<legend>{{ form.title }}</legend>
{{ form }}
</fieldset>
</li>
{% endfor %}
<li class="object">
<h2>
<label for="id_rules">Rules</label>

View File

@@ -22,22 +22,12 @@ def register_admin_urls():
]
class SegmentCreateView(CreateView):
def get_context_data(self, **kwargs):
context = {
'additional_forms': (TimeRuleForm, ReferralRuleForm, VisitCountRuleForm),
}
context.update(kwargs)
return super(SegmentCreateView, self).get_context_data(**context)
class SegmentModelAdmin(ModelAdmin):
"""The base model for the Segments administration interface."""
model = Segment
menu_icon = 'group'
add_to_settings_menu = False
list_display = ('status', 'name', 'create_date', 'edit_date')
create_view_class = SegmentCreateView
index_view_extra_css = ['personalisation/segment/index.css']
form_view_extra_css = ['personalisation/segment/form.css']
inspect_view_enabled = True