7

adds variation add view and fixes tests

This commit is contained in:
Boris Besemer
2016-11-15 13:36:41 +01:00
parent 0746352ed6
commit ce59df3f0a
10 changed files with 178 additions and 30 deletions

View File

@ -1,7 +1,6 @@
[tool:pytest]
DJANGO_SETTINGS_MODULE = tests._sandbox.settings
norecursedirs = .tox .git
django_find_project = true
[flake8]
ignore=E731

View File

@ -1,5 +1,17 @@
from setuptools import find_packages, setup
install_requires = [
'django-polymorphic==1.0.2',
'wagtail>=1.7',
]
tests_require = [
'pytest==3.0.4',
'pytest-django==3.0.0',
'pytest-sugar==0.7.1',
]
setup(
name='wagtail-personalisation',
version='0.1.0',
@ -7,6 +19,11 @@ setup(
author='Lab Digital BV',
author_email='b.besemer@labdigital.nl',
url='http://labdigital.nl',
install_requires=install_requires,
tests_require=tests_require,
extras_require={
'test': tests_require,
},
packages=find_packages('src'),
package_dir={'': 'src'},
include_package_data=True,
@ -27,8 +44,4 @@ setup(
'Framework :: Django :: 1.10',
'Topic :: Internet :: WWW/HTTP :: Site Management',
],
install_requires=[
'django-polymorphic==1.0.2',
'wagtail>=1.7',
]
)

View File

@ -8,19 +8,29 @@ class TimeRuleAdminInline(admin.TabularInline):
model = models.TimeRule
extra = 0
class ReferralRuleAdminInline(admin.TabularInline):
"""Inline the Referral Rule into the administration interface for segments"""
"""
Inline the Referral Rule into the administration interface for segments
"""
model = models.ReferralRule
extra = 0
class VisitCountRuleAdminInline(admin.TabularInline):
"""Inline the Visit Count Rule into the administration interface for segments"""
"""
Inline the Visit Count Rule into the administration interface for segments
"""
model = models.VisitCountRule
extra = 0
class SegmentAdmin(admin.ModelAdmin):
"""Add the inlines to the Segment admin interface"""
inlines = (TimeRuleAdminInline, ReferralRuleAdminInline, VisitCountRuleAdminInline)
inlines = (
TimeRuleAdminInline, ReferralRuleAdminInline,
VisitCountRuleAdminInline
)
admin.site.register(models.Segment, SegmentAdmin)

View File

@ -6,12 +6,19 @@ from personalisation import views
app_name = 'segment'
urlpatterns = [
url(r'^segment/(\d+)/$', views.overview, name='overview'),
# url(r'^segment/create/$', views.CreateSegmentView.as_view(), name='create'),
url(r'^segment/(?P<segment_id>[0-9]+)/enable/$', views.enable, name='enable'),
url(r'^segment/(?P<segment_id>[0-9]+)/disable/$', views.disable, name='disable'),
url(r'^segment/(\d+)/$', views.overview,
name='overview'),
url(r'^segment/(?P<segment_id>[0-9]+)/enable/$', views.enable,
name='enable'),
url(r'^segment/(?P<segment_id>[0-9]+)/disable/$', views.disable,
name='disable'),
# TODO: These might no longer be needed when using a modal
url(r'^segment/time-rule/$', views.time_rule_embed, name="time_rule_embed"),
url(r'^segment/referral-rule/$', views.referral_rule_embed, name="refferal_rule_embed"),
url(r'^segment/visit-count-rule/$', views.visit_c_rule_embed, name="visit_count_rule_embed"),
url(r'^segment/time-rule/$', views.time_rule_embed,
name="time_rule_embed"),
url(r'^segment/referral-rule/$', views.referral_rule_embed,
name="refferal_rule_embed"),
url(r'^segment/visit-count-rule/$', views.visit_count_rule_embed,
name="visit_count_rule_embed"),
url(r'^(?P<page_pk>\d+)/add/(?P<segment_name>[^/]+)/$',
views.AddVariation.as_view(), name='add')
]

View File

@ -12,33 +12,42 @@ from personalisation.models import (
class SegmentForm(forms.ModelForm):
"""Custom Segment form for the create view."""
class Meta:
"""Why does this need a docstring? I do not know."""
model = Segment
fields = (
'name',
'status',
)
class TimeRuleForm(WagtailAdminModelForm):
"""Create a form for the time rule model."""
title = "Time"
description = "Choose a time segment in which the user visits the site."
description = """
Choose a time segment in which the user visits the site.
"""
class Meta:
model = TimeRule
fields = ['start_time', 'end_time']
class ReferralRuleForm(WagtailAdminModelForm):
"""Create a form for the referral rule model."""
title = "Referrer"
description = "Define a referring page, domain or query the user has to come from."
description = """
Define a referring page, domain or query the user has to come from.
"""
class Meta:
model = ReferralRule
fields = ['regex_string']
class VisitCountRuleForm(WagtailAdminModelForm):
"""Create a form for the visit count rule model."""
title = "Visit count"
description = "Choose the number of visits the user has to have made."
class Meta:
model = VisitCountRule
fields = ['operator', 'count']
@ -76,7 +85,6 @@ class PersonalisationForm(forms.Form):
return Page.objects.filter(pk=self.site.root_page.pk)
return qs
def _page_has_required(self, page):
common_fields = set(PersonalisablePage._meta.fields)
specific_fields = set(page.specific._meta.fields) - common_fields

View File

@ -6,7 +6,6 @@ from personalisation.models import AbstractBaseRule, Segment
logger = logging.getLogger()
class SegmentMiddleware(object):
"""Middleware for testing and putting a user in a segment"""

View File

@ -82,7 +82,6 @@ class AbstractBaseRule(PolymorphicModel):
return "Segmentation rule"
@python_2_unicode_compatible
class TimeRule(AbstractBaseRule):
"""Time rule to segment users based on a start and end time"""
@ -195,6 +194,7 @@ class VisitCountRule(AbstractBaseRule):
operator_display = self.get_operator_display()
return '{} {}'.format(operator_display, self.count)
class AdminPersonalisablePageForm(WagtailAdminPageForm):
def __init__(self, *args, **kwargs):
super(AdminPersonalisablePageForm, self).__init__(*args, **kwargs)
@ -297,7 +297,8 @@ def get_edit_handler(cls):
if cls.settings_panels:
tabs.append(ObjectList(cls.settings_panels, heading=_("Settings"), classname='settings'))
EditHandler = TabbedInterface(tabs, base_form_class=cls.base_form_class)
return EditHandler.bind_to_model(cls)
edit_handler = TabbedInterface(tabs, base_form_class=cls.base_form_class)
return edit_handler.bind_to_model(cls)
PersonalisablePage.get_edit_handler = get_edit_handler

View File

@ -2,21 +2,25 @@ from __future__ import absolute_import, unicode_literals
from django.forms import ModelForm
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import get_object_or_404, render
from django.shortcuts import get_object_or_404, render, redirect
from django.urls import reverse
from django.utils.translation import ugettext_lazy as _
from django.views.generic.edit import FormView
from wagtail.contrib.modeladmin.views import CreateView
from wagtail.wagtailadmin.edit_handlers import (
FieldPanel, ObjectList, PageChooserPanel, TabbedInterface)
from personalisation.forms import (
ReferralRuleForm, SegmentForm, TimeRuleForm, VisitCountRuleForm)
from personalisation.models import (
ReferralRule, Segment, TimeRule, VisitCountRule)
PersonalisationForm, ReferralRuleForm, SegmentForm, TimeRuleForm,
VisitCountRuleForm)
from personalisation.models import PersonalisablePage, Segment
def overview(request):
"""Display segments overview. Dummy function"""
return render(request, 'wagtailadmin/segment.html')
def enable(request, segment_id):
"""Enable the selected segment"""
segment = get_object_or_404(Segment, pk=segment_id)
@ -25,6 +29,7 @@ def enable(request, segment_id):
return HttpResponseRedirect(request.META.get('HTTP_REFERER', '/'))
def disable(request, segment_id):
"""Disable the selected segment"""
segment = get_object_or_404(Segment, pk=segment_id)
@ -33,29 +38,87 @@ def disable(request, segment_id):
return HttpResponseRedirect(request.META.get('HTTP_REFERER', '/'))
# TODO: Make these requestable from an existing page (the create page.)
# TODO: Make these requestable from an existing page (the create page)
# This code might become obsolete.
def time_rule_embed(request):
"""Show the content of the time rule modal."""
return render(request, 'wagtailadmin/embeds/time_rule.html', {
'form': TimeRuleForm,
})
def referral_rule_embed(request):
"""Show the content of the referral rule modal."""
return render(request, 'wagtailadmin/embeds/referral_rule.html', {
'form': ReferralRuleForm,
})
def visit_c_rule_embed(request):
def visit_count_rule_embed(request):
"""Show the content of the visit count rule modal."""
return render(request, 'wagtailadmin/embeds/visit_count_rule.html', {
'form': VisitCountRuleForm,
})
class CreateSegmentView(CreateView):
page_title = _("Add segment")
form_class = SegmentForm
template_name = 'modeladmin/personalisation/segment/create.html'
header_icon = 'folder-open-1'
class AddVariation(FormView):
form_class = PersonalisationForm
add_variation_panels = [
FieldPanel('copy_from_canonical'),
PageChooserPanel('parent_page'),
]
edit_handler = TabbedInterface([
ObjectList(add_variation_panels, heading='Variation',
base_form_class=PersonalisationForm)
])
def dispatch(self, request, page_pk, segment_name, *args, **kwargs):
self.page = get_object_or_404(PersonalisablePage, pk=page_pk)
self.segment = get_object_or_404(Segment, name=segment_name)
super(AddVariation, self).dispatch(request, *args, **kwargs)
def get_form_kwargs(self):
form_kwargs = super(AddVariation, self).get_form_kwargs(*args, **kwargs)
form_kwargs.update({
'page': self.page,
'segment': self.segment,
})
return form_kwargs
def form_valid(self, form):
parent = form.cleaned_data['parent_page']
copy_from_canonical = form.cleaned_data['copy_from_canonical']
new_page = self.page.create_variation(
self.segment, copy_fields=copy_from_canonical, parent=parent)
return redirect(
'wagtailadmin_pages:edit', new_page.id
)
def get_context_data(self, *args, **kwargs):
context = super(AddVariation, self).get_context_data(*args, **kwargs)
edit_handler = self.edit_handler.bind_to_model(self.page)
context.update({
'page': self.page,
'segment': self.segment,
'content_type': self.page.content_type,
'parent_page': self.page.get_parent(),
'edit_handler': edit_handler(self.page, context['form']),
})
return context

View File

@ -21,6 +21,7 @@ def register_admin_urls():
namespace='personalisation')),
]
class SegmentCreateView(CreateView):
def get_context_data(self, **kwargs):
context = {

47
tests/conftest.py Normal file
View File

@ -0,0 +1,47 @@
from django.conf import settings
def pytest_configure():
settings.configure(
MIDDLEWARE_CLASSES=[
'django.contrib.sessions.middleware.SessionMiddleware',
'personalisation.middleware.SegmentMiddleware',
],
CACHES={
'default': {
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
'LOCATION': 'unique-snowflake',
}
},
DATABASE={
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': 'db.sqlite',
},
},
INSTALLED_APPS=[
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'wagtail.contrib.modeladmin',
'personalisation',
],
TEMPLATES=[
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
)