Miscellaneous jQuery Mobile + Django tips

Some little tips on how to make your "normal" Django site work properly under jQuery mobile:

  • as mentioned before, put your JQM setup code into a base template that all of your mobile pages extend, this means that users can go to any "normal" url and still get the jQuery effects loaded
  • create a "content" and "title" block (at least), much as you would on a normal page template, map those into the JQM data-role=header/content so that you don't have any particularly JQM markup in the individual pages; provide your navigation, django message-display and login/logout buttons in the overall page template, use the JQM theme system if possible to control display of these elements
  • adding data-role="none" is necessary if you want to keep a particular field from being "mobile-ized" (e.g. image inputs, which are somewhat useless when mobile-ized)
  • adding rel="external" (or the like) is necessary if you want to have a particular URL not use the JQM transition machinery (e.g. if it is a download link or a link to e.g. the django admin portal or some other non-JQM part of your site)
  • adding data-json="false" is useful when you are doing POSTs to the same URL as the form get (i.e. the normal pattern), this will cause POSTS to *not* use JQM's page transitions, but it avoids lots of nasty history artifacts, both from "errors-occurred" reloading of the same page with errors displayed and from "success" redirect to a new URL
  • avoid redirects whenever possible (basically for everything save your form POSTS), they just confuse JQM if it follows the link through the redirect; you can try setting data-url={{request.path}} on the page instance, but so far this seems hit-and-miss wrt avoiding duplicate pages
  • your page-level (page-specific) scripts must be children of the page node (this is a JQM work-around).  You will likely have written your template so that the script could be included in the "content" section, but a separate block can be used as well (as long as it is a child of the page).
  • hooking your script up to the page on which it is working is a bit painful, because of JQM's issues with redirects, reloading the same page, etceteras, it is quite common to have the same page (with the same ID, classes, etceteras, obviously) loaded twice in the DOM.  Thus the tutorials which suggest using #page-id to find the page are going to break in the real world (your javascript will find the old page, rather than the new one, by default).  I haven't found a *good* solution for this one yet, I'm just trying to avoid the issues for now.  In theory using data-url={{request.path}} should work to mitigate the issues, but so far I haven't seen that work in practice.  I've also tried altering e.g. the ID of the page on load (so subsequent loads of the same script wouldn't find it), which seemed to confuse JQM too much to make it worthwhile; I may try adding/removing a class on pagecreate to allow for distinguishing between the two pages
  • use named URLs and {% url name %} (in templates) or reverse( name ) to provide all URLs, this has the effect of canonicalizing the urls (as well as giving you a flexible URL mapping, of course), which avoids the nastiness where you load the same page with e.g. '/' or '/.' at the end versus the same url without
  • JQM doesn't clean up pages, they are all still loaded in your DOM as you browse the rest of the site.  Bind the pagehide event on all divs and do a page.remove() to get rid of the page (at the cost of forcing a reload if you return to the page).  If you wanted, you could do a little timer to unload after 2 minutes if you don't return (cancel the timer if the page gets a pageshow)
  • Watch out for assumptions regarding layout in some of the JQM stylesheets, for instance, listviews, by default, will do a "margin: -15px" to override the default content padding of 15px; which means if you have content followed by a listview, the content will get a nasty 15px overlap.  The assumption is that there's either a listview, or nothing, and your "summary bar" or "messages bar" at the top of the view doesn't fit that assumption
Anyway, hopefully that will be enough to help you get started using JQM with your Django sites.


  1. Castaway

    Castaway on 01/26/2012 2:53 a.m. #

    I Have a question concerning "adding data-json="false" is useful when you are doing POSTs"

    my request for login looks like
    if request.method == 'POST':
    username = request.POST['u']
    password = request.POST['p']
    user = authenticate(username=username, password=password)

    where do i put the ---data-json="false"---? Tried it in various way. but couldn't find the solution

    GREAT Tips !

  2. Mike Fletcher

    Mike Fletcher on 01/26/2012 7:34 a.m. #

    You add it on the form view; jquery mobile uses it to say "do this post as a regular request rather than a json request".

  3. Castaway

    Castaway on 01/27/2012 3:49 a.m. #

    hmmm thanks for answering...because i'm kind of a starter with django und JQM
    1.) can you post an example of how to use data-json="false"...that would be sooo awesome!

    By the way...i kind of switched off ajax writing the following in the template:

    <script type="text/javascript">
    $(document).bind("mobileinit", function(){

    It helps to with log-in forms but seems to not fully switch off ajax...*grr*

    2.) Do you have experience with sencha? Is that more Django compatible?

    Greetings from Berlin, Germany

Comments are closed.


Pingbacks are closed.