• Stars
    star
    151
  • Rank 246,057 (Top 5 %)
  • Language
    Python
  • License
    BSD 3-Clause "New...
  • Created almost 13 years ago
  • Updated over 11 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Simple Django backends for Backbone.js apps.

Djangbone

Djangbone is a small django app that makes it easy to work with Backbone.js frontends. More specifically, it allows you to quickly build a web API that works with the default Backbone.sync implementation.

Djangbone provides one abstract class-based view (BackboneAPIView), which has a bunch of hooks for customization.

Example Usage

After downloading/installing djangbone, all you need to do is:

  1. Subclass BackboneAPIView, and set the base_queryset and serialize_fields attributes.
  2. Wire up the view subclass in your urlconf.

For example, in myapp/views.py:

from myapp.models import Widget
from djangbone.views import BackboneAPIView

class WidgetView(BackboneAPIView):
    # base_queryset is a queryset that contains all the objects that are
    # accessible by the API:
    base_queryset = Widget.objects.all()

    # serialize_fields is a list of model fields that you want to be sent
    # in your JSON resonses:
    serialize_fields = ('id', 'name', 'description', 'created_at')

In myapp/urls.py:

from myapp.views import WidgetView

# Create url patterns for both "collections" and single items:
urlpatterns = patterns('',
    url(r'^widgets$', WidgetView.as_view()),
    url(r'^widgets/(?P<id>\d+)', WidgetView.as_view()),
)

If you want to run the djangbone tests, you'll need to add "djangbone" to your INSTALLED_APPS, and run python manage.py test djangbone. The tests use django.contrib.auth, so that app will also need to be in your INSTALLED_APPS for the tests to work.

Handling POST and PUT requests

Backbone.sync uses POST requests when new objects are created, and PUT requests when objects are changed. If you want to support these HTTP methods, you need to specify which form classes to use for validation for each request type.

To do this, give your BackboneAPIView subclass add_form_class and edit_form_class attributes. Usually you'll want to use a ModelForm for both, but regardless, each form's save() method should return the model instance that was created or modified.

Here's an example (assume AddWidgetForm and EditWidgetForm are both ModelForms):

from djangbone.views import BackboneAPIView
from myapp.models import Widget
from myapp.forms import AddWidgetForm, EditWidgetForm

class WidgetView(BackboneAPIView):
    base_queryset = ...
    serialize_fields = ...
    add_form_class = AddWidgetForm      # Used for POST requests
    edit_form_class = EditWidgetForm    # Used for PUT requests

If you need access to the request object in your form classes (maybe to save request.user to your model, or perform extra validation), add a set_request() method to your form classes as follows:

class AddWidgetForm(ModelForm):
    class Meta:
        model = Widget

    def set_request(self, request):
        self.request = request

    # Now you have access to self.request in clean() and save()

Pagination

If you want to limit the number of items returned for a collection, you can turn on basic pagination with BackboneAPIView's page_size attribute. Set it to an integer and GETs without an id will be paginated. The default GET parameter is "p", but you can override this with BackboneAPIView.page_param_name.

Customization

There's a decent chance that you'll want to wrap your BackboneAPIView subclass with additional functionality, for example to only allow registered users to access this view. You can use django's method_decorator on BackboneAPIView's dispatch() method to do this as follows:

from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator

class WidgetView(BackboneAPIView):
    ...

    @method_decorator(login_required)
    def dispatch(self, request, *args, **kwargs):
        return super(WidgetView, self).dispatch(*args, **kwargs)

You might also want to vary the base_queryset depending on the request (or an extra url parameter). You can also override dispatch() to do this, for example:

class WidgetView(BackboneAPIView):
    base_queryset = Widgets.objects.all()

    def dispatch(self, request, *args, **kwargs):
        if request.method in ['PUT', 'DELETE']:
            self.base_queryset = Widgets.objects.filter(owner=request.user)
        return super(WidgetView, self).dispatch(*args, **kwargs)

A Note on CSRF Protection

Backbone.sync sends POST request data as JSON, which doesn't work so well with Django's built-in CSRF middleware (the latter expects form-encoded POST data). As a result, if you're using the CSRF middleware, you'll want to either:

  1. Wrap your BackboneAPIView's dispatch method with the csrf_exempt decorator to disable CSRF protection, or...

  2. (recommended) In javascript, configure jQuery's ajax method to always send the X-CSRFToken HTTP header. See the Django CSRF docs for one way to do it, or if you have {% csrf_token %} somewhere in your Django template you can use something like:

    // Setup $.ajax to always send an X-CSRFToken header:
    var csrfToken = $('input[name=csrfmiddlewaretoken]').val();
    $(document).ajaxSend(function(e, xhr, settings) {
        xhr.setRequestHeader('X-CSRFToken', csrfToken);
    });
    

Requirements

Djangbone uses class-based views, and as such will only work with Django 1.3 and above. Python 2.6+ is also required.

Djangbone makes a few assumptions about your models in order to work:

  • Your model has an integer primary key named 'id' (Django creates this field by default).
  • The model fields in serialize_fields can be serialized to JSON. This isn't a problem for simple CharFields, IntegerFields, etc, but more complex fields will not work by default. You can fix this by overriding BackboneAPIView.json_encoder with your own JSONEncoder subclass. See the djangbone source for an example of this, which adds support for serializing datetime instances.

Alternatives

Djangbone is designed to be a simple way to serialize your models to JSON in a way that works with Backbone. It's not trying to be a generalized, format-agnostic API generator. If that's what you're looking for, you probably will want to go with something like django-tastypie or django-piston instead.

If you're already using django-tastypie, or are looking for a more full-featured API backend than Djangbone provides, you may want to look at backbone-tastypie, which overrides Backbone.sync (via javascript) in a way that works nicely with tastypie.

More Repositories

1

envalid

Environment variable validation for Node.js
TypeScript
1,357
star
2

JSnoX

A concise, expressive way to build React DOM in pure JavaScript.
JavaScript
230
star
3

hyperpaper-planner

Dayplanner pdf for large e-readers (eg Remarkable 2, Supernote, Kindle Scribe, Boox)
70
star
4

apollo-local-query

Simpler server rendering with apollo-client 1.x, using a local GraphQL networkInterface
JavaScript
65
star
5

backprop

Use ES5 properties with Backbone. Goodbye get() and set()!
JavaScript
51
star
6

bs-d3

Experimental d3 5.x bindings for BuckleScript
Reason
43
star
7

dotfiles

Just my dotfiles - neovim, tmux, hammerspoon
Perl
34
star
8

shmup.re

Learning Reason/OCaml by making an old-school canvas game.
OCaml
24
star
9

af.github.com

Silly little personal site
TypeScript
11
star
10

shamus

A HUD for project automation.
JavaScript
5
star
11

garbagepatch.js

Bookmarklet that reports on the global variables on a page.
JavaScript
4
star
12

HMR-time

Experiments with webpack's Hot Module Replacement
JavaScript
2
star
13

openra_chart

JavaScript
2
star
14

js1k_harness

A collection of command-line tools for developing JS1K submissions.
JavaScript
2
star
15

turrentine

A very simple CMS for django with a different take on WYSIWYG editing. See the README for more details.
Python
2
star
16

canvasulative

A fun little canvas game, based on http://www.guylima.com/cumulative/
JavaScript
1
star
17

wiseau

A build tool for client-side javascript.
JavaScript
1
star
18

test-ts-action

TypeScript
1
star
19

promises-talk

JavaScript
1
star
20

faction

Wrangle your flux/redux actions
JavaScript
1
star
21

votesplit2011

How did "vote-splitting" affect the 2011 Canadian election?
JavaScript
1
star
22

react-talk

Lunch & learn talk on React.js
JavaScript
1
star
23

tap-extras

Wraps the tap-parser npm module to also parse extra lines (stack traces, etc)
JavaScript
1
star