We are living what some people call the “mobile explosion”, a time where an increasing number of portable devices — like tablets and smartphones — are becoming a significant part of the Web. This is the reason why having your website tailored for these devices is becoming increasingly important.
Fortunately, Django is one of the few web frameworks that makes this an easy problem to solve.
How we solved it
A simple way is to create a separate settings module for the mobile version. Doing this, we’re able to run two different webapps while reusing the existing codebase. Also, each version can have its own template directory, URL root configuration, etc.
Let’s do this. In the project root directory, create a file m_settings.py with the following content:
# File: myproject/m_settings.py """Django settings for the mobile-specific website. """ # Load the default settings from settings import * # Domain "m.mydomain.com" SITE_ID = 2 PREPEND_WWW = False # Used elsewhere to determine which version is running DEFAULT_VERSION = False MOBILE_VERSION = True # URLs for the mobile version ROOT_URLCONF = 'myproject.m_urls' # Templates for the mobile version TEMPLATE_DIRS = ( os.path.normpath(os.path.dirname(__file__) + '/template/mobile'), ) # Other settings...
These two webapps share the same codebase, but that doesn’t mean they have to use the same URL root configuration. In fact, websites suitable for mobile devices are usually simpler, with fewer URL mappings.
To define separate URL root configuration for the mobile version, create a file m_urls.py with the following content:
# File: myproject/m_urls.py """Mobile-specific URL definition. """ from django.conf import settings from django.conf.urls.defaults import * # from django.contrib import admin # admin.autodiscover() # Error page handlers handler404 = 'website.views.error_404_handler' handler500 = 'website.views.error_500_handler' # Root URL patterns urlpatterns = patterns('', # I18N (r'^i18n/', include('django.conf.urls.i18n')), # Internal apps (r'^contact/', include('contact.urls')), # (r'^admin/doc/', include('django.contrib.admindocs.urls')), # (r'^admin/', include(admin.site.urls)), # Other settings... )
Note that, in this particular example, the Admin app isn’t accessible from mobile version. This just shows that we can structure each webapp differently without too much trouble.
Developing
You already know how to run the development server for the default version. Most people don’t know, however, that it’s possible to choose a different port number and settings module, which allows us to launch one development server for each webapp version:
# Terminal window 1: default version $ python manage.py runserver 8000 # Terminal window 2: mobile version $ python manage.py runserver --settings=m_settings 8001
Just develop your stuff and see the results in both versions right away. Easy peasy.
Testing
You probably noticed that we have two settings that can be used to identify what webapp version is being run, DEFAULT_VERSION and MOBILE_VERSION.
So it’s just a matter of checking those settings when you need to do different things in each webapp version. This is particularly useful when you use an app in both versions and want to create separate tests for each version:
# File: myproject/myapp/tests/__init__.py """Unit tests module for MyApp. """ from django.conf import settings if getattr(settings, 'DEFAULT_VERSION', False): # Tests the default version from default_models_tests import * from default_navigation_tests import * if getattr(settings, 'MOBILE_VERSION', False): # Tests the mobile version from mobile_models_tests import * from mobile_navigation_tests import *
We can run the tests for each version in a similar way we did before with the runserver command:
# Default version $ python manage.py test [appname...] # Mobile version $ python manage.py test --settings=m_settings [appname...]
Deploying
Despite what you may think, this is the easy part.
Since deploying Django with Apache and mod_wsgi is the recommended way to get Django into production, it’s likely that you already have a WSGI file like this:
import os, sys APPS_PATH = '/home/user/wsgi_apps' MYPROJECT_PATH = '%s/myproject' % APPS_PATH # Third-party eggs import site site.addsitedir('/home/user/.python/lib') sys.path += [APPS_PATH, MYPROJECT_PATH] os.environ['DJANGO_SETTINGS_MODULE'] = 'myproject.settings' import django.core.handlers.wsgi application = django.core.handlers.wsgi.WSGIHandler()
All we need to do is configure another WSGI-enabled subdomain on our server, e.g. m.mywebsite.com, that refers to another WSGI file like this one:
import os, sys APPS_PATH = '/home/user/wsgi_apps' MYPROJECT_PATH = '%s/myproject' % APPS_PATH # Third-party eggs import site site.addsitedir('/home/user/.python/lib') sys.path += [APPS_PATH, MYPROJECT_PATH] os.environ['DJANGO_SETTINGS_MODULE'] = 'myproject.m_settings' # This line import django.core.handlers.wsgi application = django.core.handlers.wsgi.WSGIHandler()
The only difference between these two WSGI files is that each one points to a different settings module. And no, you don’t need to have a separate copy for each version. We are using the same codebase for both versions, remember?
Minimizing the traffic
Amazingly, not everyone has access ultra-fast internet connections on their devices, so it’s very important to keep your sites as lightweight as possible.
There are several open source projects that try to address this problem. One of them is django-compress, a Django app that provides an automated system for compressing CSS and JavaScript files.
In fact, doesn’t matter if your websites target mobile devices or not; you should always try to minimize the amount of traffic.
What’s left?
There’s one small problem though: when someone visit the regular website from a mobile device, or vice-versa, they are not redirected to the appropriate version. But this is a topic for another article!
Posts em Português
Posts in English
Pingback: Tweets that mention Django For Mobile Devices | Destaqueblog -- Topsy.com