7

Compare commits

...

1 Commits

Author SHA1 Message Date
2ae115c72f Added visit page view
Fixes #74

Allows frontend users to submit page views and retrieve segments while
behind a cache or CDN.
2017-05-31 15:48:41 +01:00
4 changed files with 113 additions and 3 deletions

View File

@ -137,7 +137,7 @@ class SessionSegmentsAdapter(BaseSegmentsAdapter):
segments = self.get_segments()
return next((s for s in segments if s.pk == segment_id), None)
def add_page_visit(self, page):
def add_page_visit(self, page, path=None):
"""Mark the page as visited by the user"""
visit_count = self.request.session.setdefault('visit_count', [])
page_visits = [visit for visit in visit_count if visit['id'] == page.pk]
@ -150,7 +150,7 @@ class SessionSegmentsAdapter(BaseSegmentsAdapter):
visit_count.append({
'slug': page.slug,
'id': page.pk,
'path': self.request.path,
'path': path or self.request.path,
'count': 1,
})

View File

@ -2,13 +2,16 @@ from __future__ import absolute_import, unicode_literals
from django import forms
from django.http import HttpResponseForbidden, HttpResponseRedirect
from django.http import HttpResponseForbidden, HttpResponseRedirect, HttpResponseBadRequest, JsonResponse
from django.shortcuts import get_object_or_404, reverse
from django.views.decorators.cache import never_cache
from django.views.decorators.http import require_POST
from django.utils.translation import ugettext_lazy as _
from wagtail.contrib.modeladmin.options import ModelAdmin, modeladmin_register
from wagtail.contrib.modeladmin.views import IndexView
from wagtail.wagtailcore.models import Page
from wagtail_personalisation.adapters import get_segment_adapter
from wagtail_personalisation.models import Segment
@ -137,3 +140,36 @@ def copy_page_view(request, page_id, segment_id):
return HttpResponseRedirect(edit_url)
return HttpResponseForbidden()
@never_cache
@require_POST
def visit_page(request):
"""Allows a frontend user to submit a page view and retrieve their current
segments on a site that is behind a cache or CDN.
On each page view, the user must POST to this view the page ID and path
that they are browsing. It will return a JSON-formatted document containing
a list of segments that are currently active for them.
"""
segment_adapter = get_segment_adapter(request)
page_id = request.POST.get('page_id')
path = request.POST.get('path')
if page_id is None or path is None:
return HttpResponseBadRequest()
page = Page.objects.filter(id=page_id).only('id', 'slug', 'live').first()
if page is None or page.live is False:
return HttpResponseBadRequest()
segment_adapter.add_page_visit(page, path=path)
segment_adapter.refresh()
return JsonResponse({
'segments': [
segment['encoded_name']
for segment in segment_adapter.get_segments()
]
})

View File

@ -5,6 +5,7 @@ from django.contrib import admin
from wagtail.wagtailadmin import urls as wagtailadmin_urls
from wagtail.wagtailcore import urls as wagtail_urls
from wagtail.wagtaildocs import urls as wagtaildocs_urls
from wagtail_personalisation.views import visit_page
urlpatterns = [
url(r'^django-admin/', include(admin.site.urls)),
@ -12,5 +13,7 @@ urlpatterns = [
url(r'^admin/', include(wagtailadmin_urls)),
url(r'^documents/', include(wagtaildocs_urls)),
url(r'^visit-page/', visit_page),
url(r'', include(wagtail_urls)),
]

View File

@ -0,0 +1,71 @@
from __future__ import absolute_import, unicode_literals
import pytest
from freezegun import freeze_time
from wagtail_factories import SiteFactory
from tests.factories.rule import DayRuleFactory
from tests.factories.segment import SegmentFactory
@pytest.mark.django_db
class TestVisitPageView(object):
def setup(self):
"""
Sets up a site root to test segmenting
"""
self.site = SiteFactory(is_default_site=True)
def test_counts_visits(self, client):
response = client.post('/visit-page/', {
'page_id': 1,
'path': 'foo',
})
assert response.status_code == 200
assert client.session['visit_count'] == [
{'slug': 'root', 'id': 1, 'path': 'foo', 'count': 1}
]
@freeze_time("2017-01-01")
def test_returns_segments(self, client):
day_only_segment = SegmentFactory(name='Day only')
DayRuleFactory(
sun=True,
segment=day_only_segment)
response = client.post('/visit-page/', {
'page_id': 1,
'path': 'foo',
})
assert response.status_code == 200
assert response.json() == {
'segments': ['day-only']
}
def test_get_request(self, client):
response = client.get('/visit-page/')
assert response.status_code == 405
def test_missing_page_id(self, client):
response = client.post('/visit-page/')
assert response.status_code == 400
def test_missing_path(self, client):
response = client.post('/visit-page/', {
'page_id': 1,
})
assert response.status_code == 400
def test_nonexistent_page(self, client):
response = client.post('/visit-page/', {
'page_id': 9999999,
'path': 'foo',
})
assert response.status_code == 400