Irrational Exuberance!

Using JQuery with Django for Autocomplete Fields

November 30, 2007. Filed under jquerydjango

This article is not particularly polished, and expects some general Django knowledge. It does not require any JQuery experience.

Using Django with JQuery for Ajax is pretty easy, but figuring out how to do do a autocomplete form can be a bit more complex. So, here is a walkthrough.

I am using Frank Vega's autocomplete library. It is a bit simple, but entirely usable. Grab the javascript, and the css. You'll also need the Dimensions plugin for JQuery, and also JQuery itself. Shove all of those things into the 'js' folder in your media folder. It should look like this:

/media
    /js
        jquery-1.2.1.js
        dimensions.js
        autocomplete.js
        autocomplete.css

Our Templates

First we're going to write out templates. We'll be using two different templates, one base template to load our javascript and css files, and another smaller one we can include wherever we want to use the autocomplete form functionality.

<html lang=en>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <link type="text/css" rel="stylesheet" href="/media/js/autocomplete.css">
    <script type="text/javascript" src="/media/js/jquery-1.2.1.js"></script>
    <script type="text/javascript" src="/media/js/dimensions.js"></script>
    <script type="text/javascript" src="/media/js/autocomplete.js"></script>
    {% block extra_css %}{% endblock extra_css %}
    <title>{% block title %}books are social{% endblock title %}</title>
  </head>
  <body>
    {% block body %}
    {% endblock body %}
  </body>
</html>

and the smaller template:

<script type="text/javascript" >
$(function(){
  setAutoComplete("bookSearchField", "bookResults", "/lookup/?query=");
});
</script>
<label for="bookSearchField">Book: </label>
<input type="text" id="bookSearchField" name="bookSearchField">

When we want to use this, use the {% include "path/to/lookup.html" %} tag to include it (assuming you name the shorter snippet as lookup.html). Note that you'll want to include the shorter snippet into a larger template that extends the base template above, so that it has the necessary javascript libraries available.

Urls

Now we'll want to make our simple urls.py that we'll be communicating with (you'll need to update the name of the project and the application in the urls.py file):

from django.conf.urls.defaults import *
urlpatterns = patterns('project.app.views',
    (r'^/lookup/$', 'book_lookup'),
)

This may require a bit of tweaking to adapt to your specific situation, but it doesn't require any magic you haven't been exposed to in the Django tutorial.

The Model

A very very simple Book model that we'll be using to search by.

class Book(models.Model):
    name = models.CharField(max_length=200)

The View

Our view is quite simple, simple parsing the incoming GET request, and sending back some serialized data.

from django.utils import simplejson
from django.http import HttpResponse
from project.app.models import Book
def user_lookup(request):
    # Default return list
    results = []
    if request.method == "GET":
        if request.GET.has_key(u'query'):
            value = request.GET[u'query']
            # Ignore queries shorter than length 3
            if len(value) > 2:
                model_results = Book.objects.filter(name__icontains=value)
                results = [ x.name for x in model_results ]
    json = simplejson.dumps(results)
    return HttpResponse(json, mimetype='application/json')

Notice we use 'name__icontains' to search by the name of the books. This will probably translate into SQL as a LIKE query, which is historically considered to be a worse idea than delivering a nuclear warhead by a mule. It will likely be quite slow on a large database. This is an example, not production quality code.

The End

And thats it for using JQuery to do some simple autocompletion. Django really does make these things quite simple, although it can be a bit confusing when you're getting started.

Let me know if you need any help.