Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
.tox/
*.pyc
4 changes: 3 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
=============
django-mobile
django-mobile (patched for Django 1.11 and 2.2)
=============

|build| |package|
Expand All @@ -19,6 +19,8 @@ steps:
2. The template loader takes then care of choosing the correct templates based
on the flavour detected in the middleware.

*The original project https://github.com/gregmuellegger/django-mobile has been abandoned. This is a fork which takes fixes from https://github.com/ProfBIT-develop/django-mobile.*


Installation
============
Expand Down
2 changes: 1 addition & 1 deletion django_mobile/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-

__author__ = u'Gregor Müllegger'
__version__ = '0.7.0.dev1'
__version__ = '0.7.1'


import threading
Expand Down
11 changes: 7 additions & 4 deletions django_mobile/cache/middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,26 @@

from django.utils.cache import patch_vary_headers
from django_mobile import get_flavour, _set_request_header
from django.utils.deprecation import MiddlewareMixin


class CacheFlavourMiddleware(object):
def __init__(self):
class CacheFlavourMiddleware(MiddlewareMixin):
def __init__(self, get_response=None):
self.get_response = get_response
warnings.warn('CacheFlavourMiddleware does nothing and should be abandoned.'
'The intended behavior cannot be implemented using one middleware.'
'Use separate FetchFromCacheFlavourMiddleware and UpdateCacheFlavourMiddleware instead.'
'Refer to https://github.com/gregmuellegger/django-mobile/pull/64 for details',
category=DeprecationWarning)
super(CacheFlavourMiddleware, self).__init__()


class FetchFromCacheFlavourMiddleware(object):
class FetchFromCacheFlavourMiddleware(MiddlewareMixin):
def process_request(self, request):
_set_request_header(request, get_flavour(request))


class UpdateCacheFlavourMiddleware(object):
class UpdateCacheFlavourMiddleware(MiddlewareMixin):
def process_response(self, request, response):
patch_vary_headers(response, ['X-Flavour'])
return response
3 changes: 2 additions & 1 deletion django_mobile/compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
from django.template.loaders.base import Loader as BaseLoader
except ImportError: # Django < 1.8
Engine = None
from django.template.loader import BaseLoader, find_template_loader, get_template_from_string
from django.template.loader import (
BaseLoader, find_template_loader, get_template_from_string)


def template_loader(loader_name):
Expand Down
12 changes: 9 additions & 3 deletions django_mobile/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ def __getattr__(self, attr):
try:
return getattr(self.defaults, attr)
except AttributeError:
raise AttributeError(u'settings object has no attribute "%s"' % attr)
raise AttributeError(
u'settings object has no attribute "%s"' % attr)


class defaults(object):
Expand All @@ -30,13 +31,18 @@ class defaults(object):
FLAVOURS_COOKIE_HTTPONLY = False
FLAVOURS_SESSION_KEY = u'flavour'
FLAVOURS_TEMPLATE_LOADERS = []
for loader in django_settings.TEMPLATE_LOADERS:
if isinstance(loader, (tuple, list)) and loader[0] == CACHE_LOADER_NAME:
loaders = []
for template_conf in django_settings.TEMPLATES:
loaders.extend(template_conf.get('OPTIONS', {}).get('loaders', []))
for loader in loaders:
if isinstance(loader, (tuple, list))\
and loader[0] == CACHE_LOADER_NAME:
for cached_loader in loader[1]:
if cached_loader != DJANGO_MOBILE_LOADER:
FLAVOURS_TEMPLATE_LOADERS.append(cached_loader)
elif loader != DJANGO_MOBILE_LOADER:
FLAVOURS_TEMPLATE_LOADERS.append(loader)
FLAVOURS_TEMPLATE_LOADERS = tuple(FLAVOURS_TEMPLATE_LOADERS)


settings = SettingsProxy(django_settings, defaults)
14 changes: 9 additions & 5 deletions django_mobile/loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
from django.template.loaders.cached import Loader as DjangoCachedLoader
from django_mobile import get_flavour
from django_mobile.conf import settings
from django_mobile.compat import BaseLoader, template_loader, template_from_string
from django_mobile.compat import (
BaseLoader, template_loader, template_from_string)
from django.utils.encoding import force_bytes


Expand All @@ -19,7 +20,7 @@ def get_template_sources(self, template_name, template_dirs=None):
for loader in self.template_source_loaders:
if hasattr(loader, 'get_template_sources'):
try:
for result in loader.get_template_sources(template_name, template_dirs):
for result in loader.get_template_sources(template_name):
yield result
except UnicodeDecodeError:
# The template dir name was a bytestring that wasn't valid UTF-8.
Expand Down Expand Up @@ -74,12 +75,14 @@ class CachedLoader(DjangoCachedLoader):

def cache_key(self, template_name, template_dirs, *args):
if len(args) > 0: # Django >= 1.9
key = super(CachedLoader, self).cache_key(template_name, template_dirs, *args)
key = super(CachedLoader, self).cache_key(
template_name, template_dirs, *args)
else:
if template_dirs:
key = '-'.join([
template_name,
hashlib.sha1(force_bytes('|'.join(template_dirs))).hexdigest()
hashlib.sha1(
force_bytes('|'.join(template_dirs))).hexdigest()
])
else:
key = template_name
Expand All @@ -91,7 +94,8 @@ def load_template(self, template_name, template_dirs=None):
template_tuple = self.template_cache.get(key)

if template_tuple is TemplateDoesNotExist:
raise TemplateDoesNotExist('Template not found: %s' % template_name)
raise TemplateDoesNotExist(
'Template not found: %s' % template_name)
elif template_tuple is None:
template, origin = self.find_template(template_name, template_dirs)
if not hasattr(template, 'render'):
Expand Down
43 changes: 28 additions & 15 deletions django_mobile/middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
from django_mobile import flavour_storage
from django_mobile import set_flavour, _init_flavour
from django_mobile.conf import settings
from django.utils.deprecation import MiddlewareMixin


class SetFlavourMiddleware(object):
class SetFlavourMiddleware(MiddlewareMixin):
def process_request(self, request):
_init_flavour(request)

Expand All @@ -18,7 +19,7 @@ def process_response(self, request, response):
return response


class MobileDetectionMiddleware(object):
class MobileDetectionMiddleware(MiddlewareMixin):
user_agents_test_match = (
"w3c ", "acs-", "alav", "alca", "amoi", "audi",
"avan", "benq", "bird", "blac", "blaz", "brew",
Expand All @@ -27,7 +28,7 @@ class MobileDetectionMiddleware(object):
"keji", "leno", "lg-c", "lg-d", "lg-g", "lge-",
"maui", "maxo", "midp", "mits", "mmef", "mobi",
"mot-", "moto", "mwbp", "nec-", "newt", "noki",
"xda", "palm", "pana", "pant", "phil", "play",
"xda", "palm", "pana", "pant", "phil", "play",
"port", "prox", "qwap", "sage", "sams", "sany",
"sch-", "sec-", "send", "seri", "sgh-", "shar",
"sie-", "siem", "smal", "smar", "sony", "sph-",
Expand All @@ -37,34 +38,46 @@ class MobileDetectionMiddleware(object):
user_agents_test_search = u"(?:%s)" % u'|'.join((
'up.browser', 'up.link', 'mmp', 'symbian', 'smartphone', 'midp',
'wap', 'phone', 'windows ce', 'pda', 'mobile', 'mini', 'palm',
'netfront', 'opera mobi',
'netfront', 'opera mobi', 'impad'
))
user_agents_exception_search = u"(?:%s)" % u'|'.join((
'ipad',
))
http_accept_regex = re.compile("application/vnd\.wap\.xhtml\+xml", re.IGNORECASE)
http_accept_regex = re.compile(
"application/vnd\.wap\.xhtml\+xml", re.IGNORECASE)

def __init__(self):
user_agents_test_match = r'^(?:%s)' % '|'.join(self.user_agents_test_match)
self.user_agents_test_match_regex = re.compile(user_agents_test_match, re.IGNORECASE)
self.user_agents_test_search_regex = re.compile(self.user_agents_test_search, re.IGNORECASE)
self.user_agents_exception_search_regex = re.compile(self.user_agents_exception_search, re.IGNORECASE)
def __init__(self, get_response=None):
self.get_response = get_response
user_agents_test_match = r'^(?:%s)' % '|'.join(
self.user_agents_test_match)
self.user_agents_test_match_regex = re.compile(
user_agents_test_match, re.IGNORECASE)
self.user_agents_test_search_regex = re.compile(
self.user_agents_test_search, re.IGNORECASE)
self.user_agents_exception_search_regex = re.compile(
self.user_agents_exception_search, re.IGNORECASE)
super(MobileDetectionMiddleware, self).__init__(
get_response=get_response)

def process_request(self, request):
is_mobile = False

if 'HTTP_USER_AGENT' in request.META :
if 'HTTP_USER_AGENT' in request.META:
user_agent = request.META['HTTP_USER_AGENT']

uc_header_key = [
k for k in request.META.keys() if 'ucbrowser' in k.lower()]
if uc_header_key and\
'android' in request.META[uc_header_key[0]].lower():
is_mobile = True
# Test common mobile values.
if self.user_agents_test_search_regex.search(user_agent) and \
not self.user_agents_exception_search_regex.search(user_agent):
if self.user_agents_test_search_regex.search(user_agent) and not\
self.user_agents_exception_search_regex.search(user_agent):
is_mobile = True
else:
# Nokia like test for WAP browsers.
# http://www.developershome.com/wap/xhtmlmp/xhtml_mp_tutorial.asp?page=mimeTypesFileExtension

if 'HTTP_ACCEPT' in request.META :
if 'HTTP_ACCEPT' in request.META:
http_accept = request.META['HTTP_ACCEPT']
if self.http_accept_regex.search(http_accept):
is_mobile = True
Expand Down