A RESTful password locker with Django and backbone.js part 2

25 May

In the first part of this series, we set up Django, created a basic Password model and created a RESTful interface for it. In this post, we’re going to set up backbone.js to load our data from our API.

Get the code

Don’t forget you can browse or clone the code from the github repo.

Javascript dependencies

Download the following dependencies and put them into a subdirectory inside a directory managed by Django’s staticfiles app. I’ve used `contrib/backbone`.

If you don’t have jQuery or Zepto installed, you’ll need one of those too.

Also create a file called `contrib/js/passwords.js` – this is where we’ll actually create our backbone application. Add all of these to your template:

    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>

    <!-- backbone -->
    <script type="text/javascript" src="{{ STATIC_URL }}contrib/backbone/ICanHaz.min.js"></script>
    <script type="text/javascript" src="{{ STATIC_URL }}contrib/backbone/json2.js"></script>
    <script type="text/javascript" src="{{ STATIC_URL }}contrib/backbone/underscore-min.js"></script>
    <script type="text/javascript" src="{{ STATIC_URL }}contrib/backbone/backbone-min.js"></script>

    <script type="text/javascript" src="{{ STATIC_URL }}/js/passwords.js"></script>

Now we’re ready to start building the backbone part of the application. My goal for this stage is just to get something up and running where it’s pulling data in via the API.

Open http://localhost:8000/passwords/ to view what we’ve currently got – data loaded via Django. We want to recreate this, but loading data using backbone.

Add the following to `contrib/js/passwords.js`:

// load the following using JQuery's document ready function
$(function(){

    // Password model
    var Password = Backbone.Model.extend({});

    // set up the view for a password
    var PasswordView = Backbone.View.extend({
        render: function () {
            // template with ICanHaz.js (ich)
            this.el = ich.passwordRowTpl(this.model.toJSON());
            return this;
        }
    });

    // define the collection of passwords
    var PasswordCollection = Backbone.Collection.extend({
        model: Password,
        url: '/api/1.0/passwords/'
    });

    // main app
    var AppView = Backbone.View.extend({
        tagName: 'tbody',

        initialize: function() {
            // instantiate a password collection
            this.passwords = new PasswordCollection();
            this.passwords.bind('all', this.render, this);
            this.passwords.fetch();
        },

        render: function () {
            // template with ICanHaz.js (ich)
            this.passwords.each(function (password) {
                $(this.el).append(new PasswordView({model: password}).render().el);
            }, this);

            return this;
        }
    });

    var app = new AppView();
    $('#app').append(app.render().el);
});

There’s not much to it. Backbone.js represents models as key-value objects to which you can add methods. We don’t need anything fancy at this stage, so we just extend the default class. Collections contain the logic for interacting with an endpoint via REST which we’ve already set up. We’ve also created a view that can render individual password objects, and one that renders the collection by delegating to the password object view.

One point worth noting in the above code is that there are no selectors in the backbone classes. This makes them reusable and more robust. The only line that contains a reference to a selector is the very last line which appends the output of the rendering of the whole application to a specific element.

The last thing to do is to create some templates. We’re using ICanHaz which includes Mustache. Update `templates/passwords/password_list.html` so it contains the following:

{% extends "base.html" %}

{% block content %}
    <h1 class="page-header">Passwords</h1>
    <table class="table table-striped" id="app">
        <thead>
          <tr>
            <th>Title</th>
            <th>User name</th>
            <th>Password</th>
            <th>Notes</th>
          </tr>
        </thead>
    </table>

    {% load verbatim %}

    <!-- ICanHaz templates -->
    {% comment %}
    Mustache and django both use {{}} tags for templates, so we need to use
    a custom template tag to output the mustache template exactly as it is.
    {% endcomment %}
    {% verbatim %}
    <script id="passwordRowTpl" type="text/html">
        <tr>
            <td>
                <a href="{{ url }}" target="_blank">
                    {{ title }}
                </a>
            </td>
            <td>{{ username }}</td>
            <td class="password">{{ password }}</td>
            <td>{{ notes }}</td>
        </tr>
    </script>
    {% endverbatim %}
{% endblock %}

Save everything and reload the page and you should see your page loading as before. If you’ve got firebug installed, open it, switch to the Net tab and reload the page to make sure that the data is being loaded remotely.

Summary

Now we’ve got a read-only application using backbone and Django, it’s time to move on and add CRUD support to the app.

Advertisements

One Response to “A RESTful password locker with Django and backbone.js part 2”

  1. Leonard 17 January, 2013 at 20:35 #

    I think this step won’t work without a “parse” function.
    http://stackoverflow.com/questions/14207378/backbone-js-collection-fetch-cant-retrieve-items

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 )

Twitter picture

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

Facebook photo

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

Google+ photo

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

Connecting to %s

%d bloggers like this: