Custom form widget for rendering an autocomplete (using jQuery UI's autocomplete widget) text input in a template.
This arose from the need to have all fields asking for a state to use autocomplete, so I decided to make this.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | # widgets.py
from django.forms.widgets import TextInput, flatatt
from django.forms.util import force_unicode
from django.utils.html import escape
from django.utils import simplejson
from django.utils.safestring import mark_safe
class AutocompleteInput(TextInput):
"""
A form text input that gets rendered as an autocomplete widget using
jQuery UI's autocomplete.
http://api.jqueryui.com/autocomplete/
The only required option is choices:
class FooForm(forms.Form):
selections = forms.CharField(max_length=10, widget=AutocompleteInput(choices=MY_SELECTIONS))
"""
def __init__(self, choices, options={}, attrs={}, *args, **kwargs):
super(TextInput, self).__init__(attrs=attrs, *args, **kwargs)
self.choices = choices
self.options = simplejson.dumps(options) if len(options) > 0 else None
self.attrs = attrs
def render(self, name, value=None, attrs={}):
final_attrs = self.build_attrs(attrs, name=name)
# Handles different types of choices
if isinstance(self.choices, list):
source = simplejson.dumps(self.choices)
elif isinstance(self.choices, str):
source = "'{0}'".format(escape(self.choices))
elif isinstance(self.choices, tuple): # assumes tuple will be 2-item choice tuples (as in the docs)
try:
## This sets the displayed values
# If you have (for example) "fruit" tuples like (('apples', 'apples'),), then you can
# just use item[0] for the "label"
# The below set up is useful for displaying the human-readable format, and inserting
# the value that will go into the database. For instance, (('FL', 'Florida'),) will
# display "Florida" but insert "FL" into the field.
source = simplejson.dumps([{"label": "{0}".format(item[1]), "value": "{0}".format(item[0])} for item in self.choices])
except IndexError:
raise ValueError("choices tuple is not valid")
else:
raise ValueError("choices type is not valid")
options = ''
if self.options:
options += ",{0}".format(self.options) # for passing add'l autocomplete options
if value:
value = force_unicode(value)
final_attrs['value'] = escape(value)
if not self.attrs.has_key('id'):
final_attrs['id'] = 'id_{0}'.format(name)
return mark_safe(u'''<input type="text" name="{0}" id="{1}" {2}>
<script type="text/javascript">
$('#{1}').autocomplete({{source:{3}{4}}});
</script>'''.format(name, flatatt(final_attrs), final_attrs['id'], source, options))
## EXAMPLE
#
# forms.py
#
from django.contrib.localflavor.us.us_states import US_STATES, US_TERRITORIES
from .widgets import AutocompleteInput
class ResidentForm(forms.ModelForm):
ALL_STATES = tuple(sorted(US_STATES + US_TERRITORIES, key=lambda obj: obj[1]))
...
state = forms.CharField(max_length=2, widget=AutocompleteInput(choices=ALL_STATES) # just use {{ form.state }} in template
...
|
More like this
- Template tag - list punctuation for a list of items by shapiromatron 10 months, 1 week ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 10 months, 2 weeks ago
- Serializer factory with Django Rest Framework by julio 1 year, 5 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 6 months ago
- Help text hyperlinks by sa2812 1 year, 6 months ago
Comments
This script seems not to work. Can you show what you included in your base template also ?
#
Please login first before commenting.