09.14
….continued from Part 1.
The code this post references can be found here: django_mobile_utils.tar.gz
I wrote my last post right after I found the solution and promised myself I’d revisit it with another post once I had cleaned it up a bit. So here it is:
I would first like to say touchè to Vijay, who pointed out there already was code to do what I was trying to accomplish. I came back over the top pounding my chest about how much faster my solution would be because it used regex, but I also felt that minidetector only got you half-way there.
Turns out when I looked at minidetector’s code, they had written a bunch of tests that showed that simple searching for substring within the user agent was faster than the regex match. You can thank Python for that. I still think mine has a few improvements.
I defaulted my code to use the string search method now, but allow you to use regex if you’d like. You can even provide your own list of search strings. Let me explain the settings:
You’ll need to add a new dictionary called MOBILE_UTILS_SETTINGS to your settings file. The only setting that is required is a tuple of paths called MOBILE_TEMPLATES_DIR. Point it to the directory where your mobile templates are (you can provide multiple values, much like django’s TEMPLATES_DIR setting).
IGNORE_LIST is a tuple of user agents that you wish to opt out of mobile flagging (say you didn’t want to deliver mobile templates to a particular browser).
If you like to provide your own user agents to search for, set the value for USER_AGENTS_FILE to the path of the file. It will be parsed for user agent strings (one on each line).
If instead of using string matches, you would like to use user agent regex from DetectMobileBrowser, you can set USE_REGEX to True.
Here’s what your settings might look like:
#settings.py ..... MOBILE_UTILS_SETTINGS = { 'MOBILE_TEMPLATES_DIR': ( # tuple of mobile template dirs (absolute paths '/path/to/mobile/templates', ), 'IGNORE_LIST':( #tuple of browsers to ignore 'ipad', 'palm', 'wap', ), 'USER_AGENTS_FILE' : '/path/to/file', # line-broken strings to match 'USE_REGEX':False # use RegEx to do the string search } ... TEMPLATE_LOADERS = ( 'django_mobile_utils.loaders.load_template_source', 'django.template.loaders.filesystem.load_template_source', 'django.template.loaders.app_directories.load_template_source', ) MIDDLEWARE_CLASSES = ( 'django.middleware.common.CommonMiddleware', 'domain.middleware.SessionMiddleware', 'django_mobile_utils.middleware.RequestMiddleware', )
You’ll notice I added the django_mobile_utils template loader and RequestMiddleware. If you add both of these to your settings, all mobile requests (based off your match criteria) will be directed first to your mobile directories to find a template before looking in your existing directories.
If you do not want ALL requests going to the mobile templates but would rather pick which django views should return a mobile template you can remove the RequestMiddleware. Instead use the is_mobile decorator like so:
#views.py from django_mobile_utils.decorators import is_mobile @is_mobile def your_django_view(request): # your code if request.mobile: #this is a mobile request return direct_to_template(request, 'template_name')
This will do two things. First, it will try and use a mobile template if its a mobile request. It will also add an boolean attribute to the request object call ‘mobile’, in case you have some specific logic you wanted to perform on a mobile request. Most likely you wont, but at least its there for you.
The django_mobile_utils module is available for download here: django_mobile_utils.tar.gz
If you have question or comments, please shoot them my way.