Version 5 (modified by 18 years ago) ( diff ) | ,
---|
An AJAX ComboBox 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 ComboBox 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.
Screenshots
The selection available after clicking the down arrow:
Selections filtered after typing the letter b:
Requirements
- simplejson 1.3 - used for object serialization.
- Dojo - used for AJAX and widget implementation. I have been using the latest SVN trunk in my project but version 0.2.2 may work for you.
- The widget tarball attached to this page.
Installation
- Install simplejson and make sure it is somewhere in your PYTHONPATH.
- Install Dojo in media/js.
- Untar nongcombobox-0.9.tar.gz and copy the
nong
directory into the same directory as dojo and copy the contents ofviews.py
into one of your ownviews.py
files.
My project layout is as follows:
myproject/ myapp/ models.py views.py urls.py templates/ myapp/ mymodel_form.html media/ js/ dojo/ nong/
Example Use
In this example we will create a form that uses the ComboBox widget to for the Article's reporter field in below.
Model
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
URLconf
Add a url to the applications urls.py
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/?search=
, which should return something like:
[["Reporter 1", 1], ["Reporter 2", 2], ...]
Template
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 to your template:
... {% block extrahead %} {% comment %} load dojo and the combobox widget {% endcomment %} <script type="text/javascript" src="/media/js/dojo/dojo.js"></script> <script type="text/javascript"> dojo.require("dojo.widget.*"); dojo.setModulePrefix("nong.widget","../nong/widget"); dojo.widget.manager.registerWidgetPackage("nong.widget"); dojo.require("nong.widget.NongComboBox"); </script> {% comment %} Add the following if you use the same template for both adding and changing. This block pre-populates the new combobox widget with the current value of the article's reporter. {% endcomment %} {% if object %} <script type="text/javascript"> function fillComboBoxes() { var reporter = dojo.widget.byId("{{ form.reporter.get_id }}"); reporter.setValue("{{ object.reporter.name }}"); reporter.setSelectedValue("{{ object.reporter.id }}"); }; dojo.addOnLoad(fillComboBoxes); </script> {% endif %} {% endblock %} ... {% comment %} Replace the usual {{ form.reporter }} element in the template with this: {% endcomment %} <select dojoType="NongComboBox" id="{{ form.reporter.get_id }}" name="reporter" dataUrl="/myapp/reporter_lookup/?search=%{searchString}" mode="remote" value="default"></select> ...
That's it! You should be able to submit this form just like you normally would.
Attachments (6)
-
nongcombobox-0.9.tar.gz
(4.0 KB
) - added by 19 years ago.
nong combobox widget
-
shot1.png
(10.4 KB
) - added by 19 years ago.
screenshot of widget in use with no text input
-
shot2.png
(4.4 KB
) - added by 19 years ago.
screenshot of widget in use after typing 'b'.
-
nongselect-1.0.tar.gz
(12.5 KB
) - added by 18 years ago.
updated select widget code
- DSC00064.JPG (19.9 KB ) - added by 18 years ago.
- kontrah.xml (260 bytes ) - added by 18 years ago.
Download all attachments as: .zip