7

Device detection and accompanying rule

Signed-off-by: Jasper Berghoef <jasper.berghoef@gmail.com>
This commit is contained in:
Jasper Berghoef
2017-01-11 15:28:40 +01:00
parent a7b477d71f
commit 597c0a50f0
5 changed files with 75 additions and 4 deletions

View File

@ -2,8 +2,8 @@ from setuptools import find_packages, setup
install_requires = [ install_requires = [
'django-polymorphic==1.0.2',
'wagtail>=1.7', 'wagtail>=1.7',
'user-agents>=1.0.1',
] ]
tests_require = [ tests_require = [

View File

@ -2,6 +2,7 @@ from __future__ import absolute_import, unicode_literals
import re import re
from datetime import datetime from datetime import datetime
from user_agents import parse
from django.db import models from django.db import models
from django.db.models.signals import pre_save from django.db.models.signals import pre_save
@ -228,6 +229,38 @@ class QueryRule(AbstractBaseRule):
return _('Query Rule') return _('Query Rule')
@python_2_unicode_compatible
class DeviceRule(AbstractBaseRule):
"""Device rule to segment users based on matching devices"""
mobile = models.BooleanField(_("Mobile phone"), default=False)
tablet = models.BooleanField(_("Tablet"), default=False)
desktop = models.BooleanField(_("Desktop"), default=False)
panels = [
FieldPanel('mobile'),
FieldPanel('tablet'),
FieldPanel('desktop'),
]
def __init__(self, *args, **kwargs):
super(DeviceRule, self).__init__(*args, **kwargs)
def test_user(self, request=None):
ua_header = request.META['HTTP_USER_AGENT']
user_agent = parse(ua_header)
if user_agent.is_mobile:
return self.mobile
elif user_agent.is_tablet:
return self.tablet
elif user_agent.is_pc:
return self.desktop
else:
return False
def __str__(self):
return _('Device Rule')
@python_2_unicode_compatible @python_2_unicode_compatible
class UserIsLoggedInRule(AbstractBaseRule): class UserIsLoggedInRule(AbstractBaseRule):
"""User should be logged in""" """User should be logged in"""

View File

@ -48,3 +48,8 @@ class QueryRuleFactory(factory.DjangoModelFactory):
class Meta: class Meta:
model = models.QueryRule model = models.QueryRule
class DeviceRuleFactory(factory.DjangoModelFactory):
class Meta:
model = models.DeviceRule

View File

@ -6,7 +6,7 @@ import pytest
from personalisation.models import Segment, TimeRule from personalisation.models import Segment, TimeRule
from tests.factories.segment import ( from tests.factories.segment import (
ReferralRuleFactory, SegmentFactory, TimeRuleFactory, DayRuleFactory) ReferralRuleFactory, SegmentFactory, TimeRuleFactory, DayRuleFactory, DeviceRuleFactory)
"""Factory tests""" """Factory tests"""
@pytest.mark.django_db @pytest.mark.django_db
@ -39,6 +39,17 @@ def test_create_segment_with_day_rule():
assert day_rule.sun is False assert day_rule.sun is False
"""DeviceRuleFactory tests"""
@pytest.mark.django_db
def test_create_segment_with_device_rule():
segment = SegmentFactory(name='DeviceSegment')
device_rule = DeviceRuleFactory(mobile=True, segment=segment)
assert device_rule.mobile is True
assert device_rule.tablet is False
assert device_rule.desktop is False
"""ReferralRuleFactory tests""" """ReferralRuleFactory tests"""
@pytest.mark.django_db @pytest.mark.django_db
def test_create_segment_with_referral_rule(): def test_create_segment_with_referral_rule():

View File

@ -9,7 +9,7 @@ from wagtail.wagtailcore.models import Page
from tests.factories.segment import ( from tests.factories.segment import (
QueryRuleFactory, ReferralRuleFactory, SegmentFactory, TimeRuleFactory, QueryRuleFactory, ReferralRuleFactory, SegmentFactory, TimeRuleFactory,
DayRuleFactory, VisitCountRuleFactory) DayRuleFactory, VisitCountRuleFactory, DeviceRuleFactory)
from tests.factories.site import SiteFactory from tests.factories.site import SiteFactory
@ -52,6 +52,28 @@ class TestUserSegmenting(object):
assert client.session['segments'][0]['encoded_name'] == 'day-only' assert client.session['segments'][0]['encoded_name'] == 'day-only'
def test_device_segment(self, client):
device_only_segment = SegmentFactory(name='Device only')
device_rule = DeviceRuleFactory(
tablet=True,
segment=device_only_segment)
client.get('/', **{'HTTP_USER_AGENT': 'Mozilla/5.0(iPad; U; CPU iPhone OS 3_2 like Mac OS X)'})
assert client.session['segments'][0]['encoded_name'] == 'device-only'
def test_device_segment_no_match(self, client):
no_device_segment = SegmentFactory(name='No device')
device_rule = DeviceRuleFactory(
mobile=True,
segment=no_device_segment)
client.get('/', **{'HTTP_USER_AGENT': 'Mozilla/5.0(iPad; U; CPU iPhone OS 3_2 like Mac OS X)'})
assert not client.session['segments']
def test_referral_segment(self, client): def test_referral_segment(self, client):
referral_segment = SegmentFactory(name='Referral') referral_segment = SegmentFactory(name='Referral')
referral_rule = ReferralRuleFactory( referral_rule = ReferralRuleFactory(
@ -59,7 +81,7 @@ class TestUserSegmenting(object):
segment=referral_segment segment=referral_segment
) )
client.get('/', **{ 'HTTP_REFERER': 'test.test'}) client.get('/', **{'HTTP_REFERER': 'test.test'})
assert client.session['segments'][0]['encoded_name'] == 'referral' assert client.session['segments'][0]['encoded_name'] == 'referral'