Device detection and accompanying rule
Signed-off-by: Jasper Berghoef <jasper.berghoef@gmail.com>
This commit is contained in:
2
setup.py
2
setup.py
@ -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 = [
|
||||||
|
@ -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"""
|
||||||
|
@ -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
|
||||||
|
@ -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():
|
||||||
|
@ -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'
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user