8

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 django.utils.translation import ugettext_lazy as _
from modelcluster.fields import ParentalKey from modelcluster.fields import ParentalKey
from modelcluster.models import ClusterableModel from modelcluster.models import ClusterableModel
from polymorphic.models import PolymorphicModel
from wagtail.utils.decorators import cached_classmethod from wagtail.utils.decorators import cached_classmethod
from wagtail.wagtailadmin.edit_handlers import ( from wagtail.wagtailadmin.edit_handlers import (FieldPanel, FieldRowPanel,
FieldPanel, MultiFieldPanel, ObjectList, PageChooserPanel, TabbedInterface) InlinePanel, MultiFieldPanel,
ObjectList, PageChooserPanel,
TabbedInterface)
from wagtail.wagtailadmin.forms import WagtailAdminPageForm from wagtail.wagtailadmin.forms import WagtailAdminPageForm
from wagtail.wagtailcore.models import Page from wagtail.wagtailcore.models import Page
from personalisation.edit_handlers import ReadOnlyWidget 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 @python_2_unicode_compatible
class AbstractBaseRule(PolymorphicModel): class AbstractBaseRule(PolymorphicModel):
"""Base for creating rules to segment users with""" """Base for creating rules to segment users with"""
segment = ParentalKey('Segment', related_name="rules")
def test_user(self, request): def test_user(self, request):
"""Test if the user matches this rule""" """Test if the user matches this rule"""
return True return True
@@ -84,12 +38,15 @@ class AbstractBaseRule(PolymorphicModel):
@python_2_unicode_compatible @python_2_unicode_compatible
class TimeRule(AbstractBaseRule): class TimeRule(AbstractBaseRule):
"""Time rule to segment users based on a start and end time""" """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")) start_time = models.TimeField(_("Starting time"))
end_time = models.TimeField(_("Ending time")) end_time = models.TimeField(_("Ending time"))
panels = [ panels = [
FieldRowPanel([
FieldPanel('start_time'), FieldPanel('start_time'),
FieldPanel('end_time'), FieldPanel('end_time'),
]),
] ]
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
@@ -113,6 +70,7 @@ class TimeRule(AbstractBaseRule):
@python_2_unicode_compatible @python_2_unicode_compatible
class ReferralRule(AbstractBaseRule): class ReferralRule(AbstractBaseRule):
"""Referral rule to segment users based on a regex test""" """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")) regex_string = models.TextField(_("Regex string to match the referer with"))
panels = [ panels = [
@@ -138,6 +96,7 @@ class ReferralRule(AbstractBaseRule):
@python_2_unicode_compatible @python_2_unicode_compatible
class VisitCountRule(AbstractBaseRule): class VisitCountRule(AbstractBaseRule):
"""Visit count rule to segment users based on amount of visits""" """Visit count rule to segment users based on amount of visits"""
segment = ParentalKey('Segment', related_name="visit_count_rules")
OPERATOR_CHOICES = ( OPERATOR_CHOICES = (
('more_than', 'More than'), ('more_than', 'More than'),
('less_than', 'Less than'), ('less_than', 'Less than'),
@@ -154,9 +113,11 @@ class VisitCountRule(AbstractBaseRule):
) )
panels = [ panels = [
PageChooserPanel('counted_page'),
FieldRowPanel([
FieldPanel('operator'), FieldPanel('operator'),
FieldPanel('count'), FieldPanel('count'),
PageChooserPanel('counted_page'), ]),
] ]
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
@@ -194,6 +155,55 @@ class VisitCountRule(AbstractBaseRule):
return '{} {}'.format(operator_display, self.count) 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): class AdminPersonalisablePageForm(WagtailAdminPageForm):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(AdminPersonalisablePageForm, self).__init__(*args, **kwargs) super(AdminPersonalisablePageForm, self).__init__(*args, **kwargs)

View File

@@ -14,19 +14,6 @@
{% block form %} {% block form %}
{{ edit_handler.render_form_content }} {{ 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"> <li class="object">
<h2> <h2>
<label for="id_rules">Rules</label> <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): class SegmentModelAdmin(ModelAdmin):
"""The base model for the Segments administration interface.""" """The base model for the Segments administration interface."""
model = Segment model = Segment
menu_icon = 'group' menu_icon = 'group'
add_to_settings_menu = False add_to_settings_menu = False
list_display = ('status', 'name', 'create_date', 'edit_date') list_display = ('status', 'name', 'create_date', 'edit_date')
create_view_class = SegmentCreateView
index_view_extra_css = ['personalisation/segment/index.css'] index_view_extra_css = ['personalisation/segment/index.css']
form_view_extra_css = ['personalisation/segment/form.css'] form_view_extra_css = ['personalisation/segment/form.css']
inspect_view_enabled = True inspect_view_enabled = True