A RESTful password locker with Django and backbone.js

25 May

In this series I’m going to show you how to use backbone.js with Django. We’re going to be creating a password locker – a site that will let you keep track of your passwords and share them with colleagues. My development environment is Fedora 16 so shell scripts are in bash.

Disclaimer: The site will evolve and to begin with will be very naive with passwords stored unencrypted in the database. Don’t use it in production 🙂

To implement a RESTful interface in Django, we’ll use Django REST framework which makes creating RESTful interfaces from Django models super easy, and gives you a nice little browser so the APIs are self-describing.

Get the code

You can browse or clone the source code for this application from github. It’s open-sourced under the MIT licence. I’ve also added tags for most of the pages so you can follow along with the tutorial if you wish.

Set up

Let’s set up the django installation quickly. I cloned my standard foundational Django project and tweaked it. It’s just a basic Django package but with a few fabric scripts that make building the project easy. It also includes user registration and authentication which we’ll need later as well as Twitter bootstrap.

You can check out my code, or install Django yourself. Once you’re set up, create a ‘passwords’ application inside an ‘apps’ directory with `mkdir apps/passwords && manage.py startapp passwords apps/passwords` – I do this so code is better namespaced instead of having application packages and other packages all mixed together:

The model

To begin with we’ll create a simple model without any user authentication. Add the following to apps/passwords/models.py:

from django.db import models

class Password(models.Model):
    Represents a username and password together with several other fields
    title = models.CharField(max_length=200)
    username = models.CharField(max_length=200,
    password = models.CharField(max_length=200)
    url = models.URLField(max_length=500,
        verbose_name='Site URL')
    notes = models.TextField(
        help_text='Any extra notes')
    created_at = models.DateTimeField(auto_now_add=True, editable=False)
    updated_at = models.DateTimeField(auto_now=True, editable=False)

    def __unicode__(self):
        return self.title

Run `./manage.py syncdb` to create your model in your database. We’ll use South to manage migrations, so convert your new password app to south with `./manage.py convert_to_south passwords`.

Now we can start the server with `./manage.py runserver`.

Now we need to create a resource for this model so Django REST framework knows how to serve it up. This is pretty simple when using a basic model. Create apps/passwords/resources.py and add the following:

from djangorestframework.resources import ModelResource
from django.core.urlresolvers import reverse
from models import Password

class PasswordResource(ModelResource):
    model = Password
    # by default, django rest framework won't return the ID - backbone.js
    # needs it though, so don't exclude it
    exclude = None
    ordering = ('-created_at',)
    # django rest framework will overwrite our 'url' attribute with its own
    # that points to the resource, so we need to provide an alternative.
    include = ('resource_url',)

    def url(self, instance):
        Return the instance URL. If we don't specify this, django rest
        framework will return a generated URL to the resource
        return instance.url

    def resource_url(self, instance):
        An alternative to the 'url' attribute django rest framework will
        add to the model.
        return reverse('passwords_api_instance',
                       kwargs={'id': instance.id})

Finally, we need to set up some URLs. To namespace all the APIs together, create an API app with `mkdir apps/api && ./manage.py startapp api apps/api` and then wire up Django REST framework by editing apps/api/urls.py:

from django.conf.urls.defaults import patterns, url

from djangorestframework.views import ListOrCreateModelView, InstanceModelView
from apps.passwords.resources import PasswordResource

my_model_list = ListOrCreateModelView.as_view(resource=PasswordResource)
my_model_instance = InstanceModelView.as_view(resource=PasswordResource)

urlpatterns = patterns('',
    url(r'^passwords/$', my_model_list, name='passwords_api_root'),
    url(r'^passwords/(?P<id>[0-9]+)/$', my_model_instance, name='passwords_api_instance'),

Also add the following to apps/passwords/urls.py to use Django’s class-based generic views to create a list view of passwords:

from django.conf.urls.defaults import patterns, url
from django.views.generic import ListView

from models import Password

urlpatterns = patterns('',
    url(r'^$', ListView.as_view(model=Password), name='password_list'),

Finally we need to include these two url.py files into the main urls.py file in your project root directory. Add the following to it inside your urlpatterns:

    url(r'^passwords/', include('apps.passwords.urls')),
    url(r'^api/1.0/', include('apps.api.urls')),

Now, we’ve got a nice browser for the API available at http://localhost:8000/api/1.0/passwords/. Open it up and check it out, and add some entries.

That’s really cool. Not only has it saved us the repetitive effort of creating a REST interface ourselves, but we can get on and populate it without using any browser extensions. It’s also validating our input using a default model form for our model, so for example it’s ensuring that input in the site URL field validates as a URL.

Finally, before we can browse the list of passwords we need to create a template in templates/passwords/password_list.html so the generic view can render the list:

{% extends "base.html" %}

{% block content %}
    <h1 class="page-header">Passwords</h1>
    <table class="table table-striped">
            <th>User name</th>
        {% for password in object_list %}
            <td>{% if password.site_url %}
                <a href="{{ password.site_url }}" target="_blank">
                    {{ password.title }}
                {% else %}
                    {{ password.title }}
                {% endif %}
            <td>{{ password.username }}</td>
            <td>{{ password.password }}</td>
            <td>{{ password.notes }}</td>
        {% endfor %}
{% endblock %}

Now, you can browse your passwords at http://localhost:8000/passwords/

Now we’ve got some data in the database, have a RESTful interface to access it and have a list of passwords on the front end, we’re ready to start ajaxing it with backbone.js. That’s in part 2.


2 Responses to “A RESTful password locker with Django and backbone.js”

  1. Leonard 6 October, 2012 at 07:18 #

    Why do I get this error?

    TemplateSyntaxError at /
    Caught ImportError while rendering: cannot import name InstanceMixin

    I can’t run any part of this code because of this, any clue?
    I didn’t find anything helpful online. Thanks

    • 10kblogger 24 October, 2012 at 16:30 #

      I’ve updated the build instructions in the README to hopefully make things a bit clearer.

      Hope it helps 🙂

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: