Version 15 (modified by anonymous, 12 years ago) (diff)


WARNING: This write-up is quite old, and has not been updated to use newforms.

An AJAX Select Widget for Django

This widget was written to replace the standard <select> form element Django uses for releated objects in forms. The widget is an extended version of the Dojo Select widget. I use this mostly in places where the number of objects in the related objects table exceeds 20 or more. The widget is extracted from a project where some tables have more than 30,000 objects and using a <select> dropdown simply did not scale. This widget supports live lookup of related fields based on a single field in that model and autocompletion.

Credit goes to Eric Moritz's original implementation for inspiring this one.


The selection available after clicking the down arrow:

screenshot of widget in use with no text input

Selections filtered after typing the letter b:

screenshot of widget in use after typing 'b'.



  • Install Dojo in media/js.
  • Untar nongselect-1.0.tar.gz and copy the nong directory into the same parent directory as dojo and copy the contents of into one of your own files.

My project layout is as follows:


Example Use

In this example we will create a form that uses the Select widget to for the Article's reporter field in below.


Using the example model from Model Examples:

from django.db import models 

class Reporter(models.Model): 
    first_name = models.CharField(maxlength=30) 
    last_name = models.CharField(maxlength=30) 
    email = models.EmailField() 

    def __str__(self): 
        return "%s %s" % (self.first_name, self.last_name) 

class Article(models.Model): 
    headline = models.CharField(maxlength=100) 
    pub_date = models.DateField() 
    reporter = models.ForeignKey(Reporter) 

    def __str__(self):
        return self.headline


Add a url to the applications for the reporter_lookup view like so:

from myproject.myapp.models import Reporter

reporter_lookup = {
        'queryset': Reporter.objects.all(),
        'field': 'first_name', # this is the field which is searched
        #'limit': 10, # default is to limit query to 10 results. Increase this if you like.
        #'login_required': False, # default is to allow anonymous queries. Set to True if you want authenticated access.

urlpatterns = patterns('',
        (r'^reporter_lookup/$', 'myproject.myapp.views.json_lookup', reporter_lookup),

Now test your new reporter_lookup view my going to http://localhost:8000/myapp/reporter_lookup/?q=, which should return something like:

[["Reporter 1", 1], ["Reporter 2", 2], ...]


Normally you would have just put {{ form.reporter }} somewhere in your article_form.html template to get a drop down menu with a list of the Reporters. To use the new widget in your form you'll need to add the following javascript and templatetags to your template:

{% load formtags %}
{% block extrahead %}
{% comment %}
load dojo and the select widget
{% endcomment %}
<script type="text/javascript" src="/media/js/dojo/dojo.js"></script>
<script type="text/javascript">
{% endblock %}
{% comment %}
Two templatetags are included for your convenience. The first, {% fieldrow ... %} splits out a form element similar in style to the
Django Admin with the field's help_text displayed.
The second, {% selectrow ... %}, splits out all the markup and javascript necessary for the AJAX select widget.

Replace the usual {{ form.reporter }} element in the template with this:
{% endcomment %}
{% fieldrow form.headline %}
{% fieldrow form.pub_date %}
{% selectrow form.reporter "/myapp/reporter_lookup/?q=%{searchString}" "first_name" %}

That's it! You should be able to submit this form just like you normally would.

Matthew Flanagan (mattimustang A T

Attachments (6)

Download all attachments as: .zip

Back to Top