Package: calband-django-mobile
django-mobileprovides a simple way to detect mobile browsers and gives
you tools at your hand to render some different templates to deliver a mobile
version of your site to the user.The idea is to keep your views exactly the same but to transparently
interchange the templates used to render a response. This is done in two
steps:A middleware determines the client’s preference to view your site. E.g. if
he wants to use the mobile flavour or the full desktop flavour.The template loader takes then care of choosing the correct templates based
on the flavour detected in the middleware.InstallationPre-Requirements:django_mobiledepends on django’s session framework. So
before you try to usedjango_mobilemake sure that the sessions framework
is enabled and working.Installdjango_mobilewith your favourite python tool, e.g. witheasy_install django_mobileorpip install django_mobile.Adddjango_mobileto yourINSTALLED_APPSsetting in thesettings.py.Adddjango_mobile.middleware.MobileDetectionMiddlewareto yourMIDDLEWARE_CLASSESsetting.Adddjango_mobile.middleware.SetFlavourMiddlewareto yourMIDDLEWARE_CLASSESsetting. Make sure it’s listedafterMobileDetectionMiddlewareand also afterSessionMiddleware.Adddjango_mobile.loader.Loaderas first item to yourloaderslist forTEMPLATESsetting insettings.py.Adddjango_mobile.context_processors.flavourto yourcontext_processorslist forTEMPLATESsetting. You can read more aboutloadersandcontext_processorsinDjango docs.Note:If you are using Django 1.7 or older, you need to change step 5 and 6 slightly. Use theTEMPLATE_LOADERSandTEMPLATE_CONTEXT_PROCESSORSsettings instead ofTEMPLATES.Now you should be able to usedjango-mobilein its glory. Read below of how
things work and which settings can be tweaked to modifydjango-mobile’s
behaviour.UsageThe concept ofdjango-mobileis build around the ideas of differentflavoursfor your site. For example themobileversion is described as
one possibleflavour, the desktop version as another.This makes it possible to provide many possible designs instead of just
differentiating between a full desktop experience and one mobile version.  You
can make multiple mobile flavours available e.g. one for mobile safari on the
iPhone and Android as well as one for Opera and an extra one for the internet
tablets like the iPad.Note:By defaultdjango-mobileonly distinguishes betweenfullandmobileflavour.After the correct flavour is somehow chosen by the middlewares, it’s
assigned to therequest.flavourattribute. You can use this in your views
to provide separate logic.This flavour is then use to transparently choose custom templates for this
special flavour. The selected template will have the current flavour prefixed
to the template name you actually want to render. This means whenrender_to_response('index.html',...)is called with themobileflavour
being active will actually return a response rendered with themobile/index.htmltemplate. However if this flavoured template is not
available it will gracefully fallback to the defaultindex.htmltemplate.In some cases its not the desired way to have a completely separate templates
for each flavour. You can also use the{{ flavour }}template variable to
only change small aspects of a single template. A short example:<html><head><title>My site{%ifflavour=="mobile"%}(mobile version){%endif%}</title></head><body>...</body></html>This will add(mobile version)to the title of your site if viewed with
the mobile flavour enabled.Note:Theflavourtemplate variable is only available if you have set up thedjango_mobile.context_processors.flavourcontext processor and used
django’sRequestContextas context instance to render the template.Changing the current flavourThe basic use case ofdjango-mobileis obviously to serve a mobile version
of your site to users. The selection of the correct flavour is usually already
done in the middlewares when your own views are called. In some cases you want
to change the currently used flavour in your view or somewhere else. You can
do this by simply callingdjango_mobile.set_flavour(flavour[, permanent=True]). The first argument is self explaining. But keep in mind
that you only can pass in a flavour that you is also in yourFLAVOURSsetting. Otherwiseset_flavourwill raise aValueError. The optionalpermanentparameters defines if the change of the flavour is remember for
future requests of the same client.Your users can set their desired flavour them self. They just need to specify
theflavourGET parameter on a request to your site. This will permanently
choose this flavour as their preference to view the site.You can use this GET parameter to let the user select from your available
flavours:<ul><li><ahref="?flavour=full">Get the full experience</a><li><ahref="?flavour=mobile">View our mobile version</a><li><ahref="?flavour=ipad">View our iPad version</a></ul>Notes on cachingDjango is shipping with some convenience methods to easily cache your views.
One of them isdjango.views.decorators.cache.cache_page. The problem with
caching a whole page in conjunction withdjango-mobileis, that django’s
caching system is not aware of flavours. This means that if the first request
to a page is served with a mobile flavour, the second request might also
get a page rendered with the mobile flavour from the cache – even if the
second one was requested by a desktop browser.django-mobileis shipping with it’s own implementation ofcache_pageto resolve this issue. Please usedjango_mobile.cache.cache_pageinstead
of django’s owncache_pagedecorator.You can also use django’s caching middlewaresdjango.middleware.cache.UpdateCacheMiddlewareandFetchFromCacheMiddlewarelike you already do. But to make them aware of
flavours, you need to adddjango_mobile.cache.middleware.FetchFromCacheFlavourMiddlewareitem before standard DjangoFetchFromCacheMiddlewarein theMIDDLEWARE_CLASSESsettings anddjango_mobile.cache.middleware.UpdateCacheFlavourMiddlewarebeforedjango_mobile.cache.middleware.UpdateCacheMiddlewarecorrespondingly.It is necessary to split the usage ofCacheMiddlewarebecause some additional work should be done on request and responsebeforestandard caching behavior and that is not possible while using two complete middlewares in either orderReferencedjango_mobile.get_flavour([request,][default])Get the currently active flavour. If no flavour can be determined it will
returndefault. This can happen ifset_flavourwas not called before
in the current request-response cycle.defaultdefaults to the first
item in theFLAVOURSsetting.django_mobile.set_flavour(flavour, [request,] [permanent])Set theflavourto be used forrequest. This will raiseValueErrorifflavouris not in theFLAVOURSsetting. You can try to set the
flavour permanently forrequestby passingpermanent=True. This may
fail if you are out of a request-response cycle.requestdefaults to the
currently active request.django_mobile.context_processors.flavourContext processor that adds the current flavour asflavourto the
context.django_mobile.context_processors.is_mobileThis context processor will add ais_mobilevariable to the context
which isTrueif the current flavour equals theDEFAULT_MOBILE_FLAVOURsetting.django_mobile.middleware.SetFlavourMiddlewareTakes care of loading the stored flavour from the user’s session or
cookies (depending onFLAVOURS_STORAGE_BACKEND) if set. Also sets the
current request to a thread-local variable. This is needed to provideget_flavour()functionality without having access to the request
object.django_mobile.middleware.MobileDetectionMiddlewareDetects if a mobile browser tries to access the site and sets the flavour
toDEFAULT_MOBILE_FLAVOURsettings value in case.django_mobile.cache.cache_pageSame as django’scache_pagedecorator, but wraps the view into
additional decorators before and after that. Makes it possible to serve multiple
flavours without getting into trouble with django’s caching that doesn’t
know about flavours.django_mobile.cache.vary_on_flavour_fetchdjango_mobile.cache.vary_on_flavour_updateDecorators created from theFetchFromCacheFlavourMiddlewareandUpdateCacheFlavourMiddlewaremiddleware.django_mobile.cache.middleware.FetchFromCacheFlavourMiddlewareAddsX-Flavourheader torequest.METAinprocess_requestdjango_mobile.cache.middleware.UpdateCacheFlavourMiddlewareAddsX-Flavourheader toresponse['Vary']inprocess_responseso that Django’sCacheMiddlewareknow that it should take into account the content of this header when looking up the cached content on next request to this URL.CustomizationThere are some points available that let you customize the behaviour ofdjango-mobile. Here are some possibilities listed:MobileDetectionMiddlewareThe built-in middleware to detect if the user is using a mobile browser served
well in production but is far from perfect and also implemented in a very
simplistic way. You can safely remove this middleware from your settings and
add your own version instead. Just make sure that it callsdjango_mobile.set_flavourat some point to set the correct flavour for
you.If you need example how tablet detection can be implemented, you can checkout themiddleware.pyfile in directoryexamples. Feel free to modify it as you like!SettingsHere is a list of settings that are used bydjango-mobileand can be
changed in your ownsettings.py:FLAVOURSA list of available flavours for your site.Default:('full', 'mobile')DEFAULT_MOBILE_FLAVOURThe flavour which is chosen if the built-inMobileDetectionMiddlewaredetects a mobile browser.Default:'mobile'FLAVOURS_COOKIE_HTTPONLYThe value that get passed intoHttpResponse.set_cookie’shttponlyargument. Set this toTrueif you don’t want the Javascript code to be
able to read the flavour cookie.Default:FalseFLAVOURS_COOKIE_KEYThe cookie name that is used for storing the selected flavour in the
browser.  This is only used ifFLAVOURS_STORAGE_BACKENDis set to'cookie'.Default:'flavour'FLAVOURS_TEMPLATE_PREFIXThis string will be prefixed to the template names when searching for
flavoured templates. This is useful if you have many flavours and want to
store them in a common subdirectory. Example:fromdjango.template.loaderimportrender_to_stringfromdjango_mobileimportset_flavourset_flavour('mobile')render_to_string('index.html')# will render 'mobile/index.html'# now add this to settings.pyFLAVOURS_TEMPLATE_PREFIX='flavours/'# and try againset_flavour('mobile')render_to_string('index.html')# will render 'flavours/mobile/index.html'Default:''(empty string)FLAVOURS_TEMPLATE_LOADERSdjango-mobile’s template loader can load templates prefixed with the
current flavour. Specify with this setting which loaders are used to load
flavoured templates.Default:same asTEMPLATE_LOADERSsetting but without'django_mobile.loader.Loader'.FLAVOURS_GET_PARAMETERUsers can change the flavour they want to look at with a HTTP GET
parameter.  This determines the name of this parameter.  Set it toNoneto disable.Default:'flavour'FLAVOURS_SESSION_KEYThe user’s preference set with the GET parameter is stored in the user’s
session. This setting determines which session key is used to hold this
information.Default:'flavour'FLAVOURS_STORAGE_BACKENDDetermines how the selected flavour is stored persistently. Available
values:'session'and'cookie'.Default:'cookie'Cache SettingsDjango ships with thecached template loaderdjango.template.loaders.cached.Loaderthat doesn’t require to fetch the
template from disk every time you want to render it. However it isn’t aware of
django-mobile’s flavours. For this purpose you can use'django_mobile.loader.CachedLoader'as a drop-in replacement that does
exactly the same django’s version but takes the different flavours into
account. To use it, put the following bit into yoursettings.pyfile:TEMPLATES=[{...'OPTIONS':{...'loaders':('django_mobile.loader.CachedLoader',('django_mobile.loader.Loader','django.template.loaders.filesystem.Loader','django.template.loaders.app_directories.Loader',)),}}]Changelog0.8.0 (in development)#68: Support recursive template inheritance in django mobile template
loader, so that we are compatible with Django’s 1.9 admin. Thanks to
@wolfg1969 for the patch.0.7.0#64: Fixingcache_pagedecorator and splitting theCacheFlavourMiddlewareinto two middlewares. This follows the same
strategy as Django did since quite a while. Please see#64for more
details about why this is necessary.If you are usingCacheFlavourMiddleware, you need to replace it now withFetchFromCacheFlavourMiddlewareandUpdateCacheMiddleware.  Please
consolidate the README for more information.Thanks to Yury Paykov for the patch.0.6.0#63: Django 1.9 support. Thanks to Alexandre Vicenzi for the patch.0.5.1#58: Fix Python 3 install issues related to unicode strings. Thanks to
Zowie for inspiring the patch.0.5.0Support for Django 1.7 and Django 1.8. Thanks to Jose Ignacio Galarza and to
Anton Shurashov for the patches.0.4.0Python 3.3 compatibility, thanks Mirko Rossini for the patch.Dropping Django 1.3 and 1.4 support.0.3.0Dropping support for python 2.5 (it might still work but we won’t test
against it anymore).Fixing threading problems because of wrong usage ofthreading.local.
Thanks to Mike Shultz for the patch.Adding a cached template loader. Thanks to Saverio for the patch.0.2.4FIX: Cookie backend actually never really worked. Thanks to demidov91 for
the report.0.2.3FIX: setflavourin all cases, not only if a mobile browser is detected.
Thanks to John P. Kiffmeyer for the report.0.2.2FIX: Opera Mobile on Android was categorized as mobile browser. Thanks to
dgerzo for the report.Sniffing for iPad so that it doesn’t get recognized as small mobile device.
Thanks to Ryan Showalter for the patch.0.2.1Fixed packing issues that didn’t include the django_mobile.cache package.
Thanks toScott Turnbullfor the report.0.2.0Restructured project layout to remove settings.py and manage.py from
top-level directory. This resolves module-name conflicts when installing
with pip’s -e option. Thanks tobendavis78for the report.Added acache_pagedecorator that emulates django’scache_pagebut
takes flavours into account. The caching system would otherwise cache the
flavour that is currently active when a cache miss occurs. Thanks toitmustbejjfor the report.Added aCacheFlavourMiddlewarethat makes django’s caching middlewares
aware of flavours. We use interally theVaryresponse header and theX-Flavourrequest header.0.1.4Fixed issue in template loader that only implementedload_template_sourcebut noload_template. Thanks to tylanpince,
rwilcox and Frédéric Roland for the report.0.1.3Fixed issue withrunservercommand that didn’t handled all request
independed from each other. Thanks to bclermont and Frédéric Roland for the
report.0.1.2Fixed unreferenced variable error inSetFlavourMiddleware.0.1.1Fixedis_usableattribute fordjango_mobile.loader.Loader. Thanks Michela Ledwidge for the report.0.1.0Initial release.