Creating a basic API with Django

Monday, August 11, 2008

Tags: programming, python, django

Creating a simple public API for your site is a lot easier than you may think with Django. You’re basically just creating another view and serving it as XML or JSON instead of HTML.

What’s public?

Decide what you want to be public. The best answer is the stuff you’re already displaying in your HTML templates. Then you need to create an entry in your url conf.

url(r'^api/v1/(?P<username>[-\w]+)/notes/?$', 'readernaut.api.views.user_notes'),

Create the view

In the case for Readernaut I wanted to provide an XML feed for users notes. Here is what the view looks like:

def user_notes(request, username):
  reader = get_object_or_404(User, username__iexact=username)
  note_list = Note.objects.filter(user=reader)
  context = { 'reader': reader, 'note_list': note_list }
  return render_to_response('api/note_list.html', context, context_instance=RequestContext(request), mimetype='application/xml')

This is a simplified version of the view but, as you can see, you could easily add pagination and other hooks to handle ordering and such.

Create the template

The view is pointing to the template api/note_list.html so all we need to do is create that file and build out our XML schema.

<?xml version="1.0" encoding="utf-8"?>
<notes version="1.0">
  {% for note in note_list %}
    <note_id>{{ }}</note_id>
      <username>{{ note.user }}</username>
      <title>{{ note.book_edition }}</title>
      <isbn>{{ note.book_edition.isbn }}</isbn>
    <body class="inner">

<header>   <h1><a href="/">Nathan Borror</a></h1> </header><![CDATA[{{ note.note }}]]></body>
    <page_reference>{{ note.page_reference }}</page_reference>
    <created>{{ note.created|date:"Y-m-d G:i T" }}</created>
    <modified>{{ note.modified|date:"Y-m-d G:i T" }}</modified>
  {% endfor %}

How you define your XML templates is up to you. I name my templates with the .html extension simply because my text editor highlights the syntax better than if it were XML. It doesn’t matter because the mime-type dictates how the file is served up. Good luck!