This library is a collection of middleware and decorators that help in creating mobile views and directing users to the mobile version of your site. It makes these assumptions:
- You can use Vary: User-Agent to serve mobile and non-mobile content through the same URLs.
- You want to use separate views and/or templates for the mobile site. If you're building a mobile experience through media queries this library won't be helpful.
- Not all views from the normal site need to be replaced with mobile views.
Written and tested on Django trunk with Python 2.6.
These are the default settings:
# A regex for detecting mobile user agents. MOBILE_USER_AGENTS = 'android|fennec|iemobile|iphone|opera (?:mini|mobi)' # The name of the cookie to set if the user prefers the mobile site. MOBILE_COOKIE = 'mobile'
You need these middleware (but see the User Agent caveats below):
MIDDLEWARE_CLASSES = (
'mobility.middleware.DetectMobileMiddleware',
'mobility.middleware.XMobileMiddleware',
)
- The
HTTP_USER_AGENTmatchesMOBILE_USER_AGENTSand theMOBILE_COOKIEis not set tooff. - or the
MOBILE_COOKIEis set toon. - A mobile view exists for the current URL.
The HTTP_USER_AGENT is checked against the regular expression in
MOBILE_USER_AGENTS. The default is a very basic set of user agents to ease
maintenance and because the cookie provides a fallback.
If MOBILE_COOKIE is set to on, through Set-Cookie or through
javascript, the mobile site will be chosen regardless of the user agent. If
MOBILE_COOKIE is set to off the normal site will always be chosen.
If the current request is for the mobile site, request.MOBILE = True. At
all other times request.MOBILE = False.
Some decorators are provided to assist with common idioms:
@mobile_template('app/{mobile/}detail.html')
def view(request, template=None):
...
@mobile_template helps with the pattern of using the same view code and
template context, but switching to a different template for mobile. It follows
this logic:
template = 'app/mobile/detail.html' if request.MOBILE else 'app/detail.html'
To use a completely different function for the mobile view:
def view(request):
...
@mobilized(view)
def view(request):
...
In the example, the first definition of view will be used for the normal
site and the second function will be used for the mobile site. The normal and
mobile site point to the same view in urls.py and the decorator handles
choosing which view to run.
Since mobile users can enter the site from any normal URL, the
DetectMobileMiddleware always inspects the User-Agent to see if it
matches something in MOBILE_USER_AGENTS, and may redirect the browser to
the mobile site. Thus, every URL on the site should be sending Vary:
User-Agent to get proper HTTP caching. Varying on User-Agent can be
detrimental to your frontend cache scheme, so it's recommended that you move
mobile detection up the stack to a frontend proxy.
The proxy can run the logic in DetectMobileMiddleware and set
HTTP_X_MOBILE (so we know whether to serve a mobile view) without varying
on user agent internally. Instead, it can vary on X-Mobile while
sending Vary: User-Agent back to the client. From the outside it looks like
the app varies on User-Agent but the proxy will only need to cache a
mobile and non-mobile version of the URL.