Josh Bohde

Using Pushstate with Backbone.js and Django

Posted by Josh Bohde

After working on a few projects with Django and Backbone, I really wanted to replace my hash-driven apps with pushstate. Django-pjax is a library aimed at making this easier for more traditional projects, but would require me to duplicate my display logic server side, without using my current mustache templates. After a few iterations, I've settled on an approach that is DRY enough for my taste. You can view the work in my django-backbone-example project.

One way to keep the project keeps templates DRY is through a template tag that renders mustache templates inline. Combined with a client side template engine, templates can be shared between the client and server. Example usage:

<div class="tweet">
{%mustache "path/to/my/tweetTemplate" tweet%}
</div>

By using Tastypie Resources in the view, the same data preparation can be used for both methods. The view from the example project is as follows:

class DetailView(TemplateView):
template_name = 'index.html'
 
def get_detail(self, pk):
tr = v1.canonical_resource_for('tweet')
 
try:
tweet = tr.cached_obj_get(pk=pk)
except Tweet.DoesNotExist:
raise Http404
 
bundle = tr.full_dehydrate(tr.build_bundle(obj=tweet))
data = bundle.data
return data
 
def get_context_data(self, **kwargs):
base = super(DetailView, self).get_context_data(**kwargs)
base['data'] = self.get_detail(base['params']['pk'])
return base

When adapting a client that already supports the hash-driven routing, it should just be a matter of altering the call to Backbone.history.start() to

Backbone.history.start({
silent: true,
pushState: true
});