Technology How To

Migrating your mobile site to Django

Tuesday, September 28, 2010 9:58 am

Overview

This guide covers how I ported the static ZSR library mobile site to Django. It covers at a very high level the various elements of Django but does not give step-by-step directions. Before taking on a project like this I highly recommend working through the mobile website tutorials listed in the related how-to and reading the Django tutorials located on the Django project site. Be sure to edit your settings.py file to setup your database connection information. For development the sqlite3 platform is very easy to work with.

Data modeling

One of the first steps in creating a Django application is creating a data model. Once you have created your new project following the instructions in tutorial 1, find your models.py file and edit it. I decided to go with a pretty concrete data model as opposed to a highly abstracted one with fewer tables. If you compare the static html mobile site with the models.py file you will see the broad organization grouped as classes (Library, External Links, Contacts) with elements that make up the data points.

Once the models are created, you can create your database by running the command python manage.py syncdb (or python manage.py sql myprojectname to see the sql). This process will create a database based on your data models and prompt you to create an administrative user. This process is documented in detail in the tutorial so give it a go & play around with entering and quering data in the python shell (towards the end of the tutorial).

Enabling the admin interface

The admin module is enabled by editing the urls.py file to uncomment the lines allowing you to import admin functions (from django.contrib import admin and admin.autodiscover). Uncomment these lines and find the URL pattern that refers to the admin url (r’^admin/…..). Uncomment this line as well.

After you do this you should be able to go to your siteurl/admin and see a complete administrative interface. Tutorial 2 takes you through the process of customizing your admin interface so I will not say much about it here. For my purposes I did not do much work to the admin system but rather spent my time working on the different views.

Writing views

In Django, views use your application models, logic and templates to output some content to a requesting client. This project contains three views related to our application. The first view, ‘detail’ outputs the core HTML page that runs the mobile site. The second view ‘feed’ outputs rss feeds based on a requested feed_id from the client. The third view ‘search’ outputs a JSON object to the requesting client in response to a search request.

Views work in conjunction with the URL configuration file. As you can see in the URL file below there is a URL entry for each view. The site and feed url copies the id of the site and calls the corresponding view. The search entry calls the search view. Once we get into the search view retrieve the passed querystring.

In the views.py file, each of these views is defined.

Feed view

The primary purpose of the feed view is to look up a feed URL in the database based on a passed feed id, retrieve that feed (assuming it is rss based xml) as pass that feed back to the client setting the mime type as application/xml. This view is very simple and does no data parsing. In our instance of the application, this view is only called via an ajax call that is bound to the startpageanimation event of the dynamically created divs. You can see all of the code by downloading the package from github

Detail view

The detail view is our most complex view. It parses some data from the database and calls our detail.html template. This in turn outputs almost the entire mobile website application to the requesting client.

One of the features of our site is a dynamically updated div that contains the most recent entry in a linked rss feed (see the library data model for where this feed is cataloged). The first thing we do is use the dom functions to retrieve the first instance of the title and link to our library twitter feed. We then build a dictionary data object called news with these two pieces of information. Finally, we call the output method and pass it the template name to use and library and news data objects to use to add data to the page.

Output templates in Django 1.2 are capable of some pretty complex stuff. You can do loops, call methods and examine data structures. I wanted to pass two separate data elements to the template for simplicity and to enable the template to be abstracted from data gathering process. For more information on the detail template, see the section on templates below.

The Search view

The search view is a pretty simple view and is very similar to the feed view. The search view starts by grabbing the contents of the lookfor variable in the querystring. Then it calls out to the catalog using a JSON api call to get some data. Finally, it passes that data back to the requesting client. The search view is only called via ajax in our site. The ajax call is bound to the submit action on our search form.

In this example the search url is hard coded which is pretty bad practice. This element should be moved to the data model so that it can be easily managed and updated.

In order to understand how to write your view and how to pass data from your view to your processing template work through the third tutorial on djangoproject.com

Expanding the template

Django Templates work by combining document output code in a template with data from the database. Templates have a number of built-in functions including loops, control variables and the ability to reference passed objects and events. Our detail template is pretty simple and only uses variable passing {{ library.libraryName }} and for loops {% for contact in library.contact %}. These two functions allow us to start pulling content out of our page. As you can see, we did not focus on creating a more abstract data model that would allow our template to be even shorter. Depending on your application you may want to embed more data and structure into your models or allow your template to contain some of that data. In our case, we wanted the different pages (contacts, locations, feeds) to behave differently so we did not try to embed all of that into the data model.

To get a sense of the use of templates, compare the template version of the “What’s New” div with the static HTML version. Even though this was a simple div element we were able to make the “What’s new section dynamic by pulling the data out and including it in a database.

In order to see the full template in action, download the project from github. This project contains all of the django code and static content you need.

Modifications to local JavaScript functions

One of the most complex changes required as part of this migration is the addition of xml and json ajax retrieval functions. In the attached file below you can see that under the $(document).ready function of jQuery we are binding two events. Our first event ($(‘#catalog’).submit()) captures the submit event of our catalog search box, passes the search string to our Django view (search) and parses the JSON data that is returned.

Our second event is bound to the pageAnimationStart event of our rss feed divs. We previously modified our Django detail template to associate the feed_id of the database with each output div as the id field. In our function call we can now access that id and pass it to Django as a parameter in our ajax call. At the server level, Django retrieves the feed cooresponding to the id and passes it back to the client as xml. The local JavaScript function takes the data and outputs it as a simple HTML list.

Many thanks to Kevin Gilbertson for helping me with these javascript calls! Although they seem daunting, the fact that we are using the jQuery framework greatly simplifies the dom element retrieval, event binding, ajax call, and document output processes. If all of this is unfamiliar to you, there is a great tutorial to jQuery at jquery.com

Enabling multiple libraries

At this point, enabling a second library is easy. We simply go to our admin page and add a second library. This updates the database and we can access this library as /site/2, site/3, etc. By updating our index page we can also create a browse-able page of library mobile sites.

First, we want to enable an index url in our urls.py file. Add a line approaching ” (r’^index/$’, ‘librware.librware_mobile.views.index’),” to your file. This tells Django to redirect calls for /index to the index views.

Second we need to create a view for index. This is not too complicated, we just need to get the Library object and pass it to our rending engine calling the index.html template:
def index(request):
libraryList = Library.objects.all()
return render_to_response(‘librware_mobile/index.html’, {‘libraryList’:libraryList}, context_instance=RequestContext(request))

Finally, we need an index.html template. To create the template I simply took the main div from our mobile site and added it to a new file which I called index.html. For more information on how templates work and where they live in your Django project see tutorial 3 on the django project website.

I cheated a bit and hard coded some values. The only loop we need here is to go through our list of cataloged libraries to add each one as a list element with a URL to point to the new site.

Save everything and load it on your favorite mobile device!

What’s next?

Despite my efforts, there are still a lot of locally dependent items in our files. The tutorial series on Django project will help you further abstract your application and variables. Next steps for this project include pulling out the variables that are hard coded in local.js and mobile.css as well as the variable hard coded in the search view.

Other items could include a more dynamic locations page, book covers and better styling on the ‘What’s New’ pages, and perhaps even a rotating information div on the main screen.


Archives
March 2012
November 2011
October 2011
June 2011
February 2011
November 2010
October 2010
September 2010
August 2010
June 2010
April 2010
February 2010
January 2010
November 2009
October 2009
September 2009
April 2009
March 2009
November 2008
August 2008
July 2008
June 2008
May 2008
April 2008
March 2008
Categories
Ad-Aware
Adobe
Adobe Acrobat
Bloglines
Blogs@ZSR
Cloud Computing
Dreamweaver
EndNote
Google
Google Sites
iphone
Macintosh
Mailmerge
Microsoft Excel
Microsoft Office
Microsoft Outlook
Microsoft PowerPoint
Microsoft Word
MovieMaker
Outreach Grant
podcasting
RSS Feed
Server Management
Spybot
Survey Tools
Uncategorized
web development
Wikis@ZSR
Zotero
Tags

Powered by WordPress.org, protected by Akismet. Blog with WordPress.com.