adds variation add view and fixes tests
This commit is contained in:
@ -1,7 +1,6 @@
|
||||
[tool:pytest]
|
||||
DJANGO_SETTINGS_MODULE = tests._sandbox.settings
|
||||
norecursedirs = .tox .git
|
||||
django_find_project = true
|
||||
|
||||
[flake8]
|
||||
ignore=E731
|
||||
|
21
setup.py
21
setup.py
@ -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',
|
||||
]
|
||||
)
|
||||
|
@ -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)
|
||||
|
@ -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')
|
||||
]
|
||||
|
@ -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
|
||||
|
@ -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"""
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
47
tests/conftest.py
Normal 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',
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
)
|
Reference in New Issue
Block a user