newforms widget for autocompleting text fields using jquery autocomplete plugin: http://jquery.bassistance.de/autocomplete/
to be implemented: - store the pk value into an hidden field - handling ChoiceFields and many others
massimo dot scamarcia at gmail.com
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 77 78 79 80 | # widgets.py
from django import newforms as forms
from django.newforms.widgets import flatatt
from django.newforms.util import smart_unicode
from django.utils.html import escape
from django.utils.simplejson import JSONEncoder
class JQueryAutoComplete(forms.TextInput):
def __init__(self, source, options={}, attrs={}):
"""source can be a list containing the autocomplete values or a
string containing the url used for the XHR request.
For available options see the autocomplete sample page::
http://jquery.bassistance.de/autocomplete/"""
self.options = None
self.attrs = {'autocomplete': 'off'}
self.source = source
if len(options) > 0:
self.options = JSONEncoder().encode(options)
self.attrs.update(attrs)
def render_js(self, field_id):
if isinstance(self.source, list):
source = JSONEncoder().encode(self.source)
elif isinstance(self.source, str):
source = "'%s'" % escape(self.source)
else:
raise ValueError('source type is not valid')
options = ''
if self.options:
options += ',%s' % self.options
return u'$(\'#%s\').autocomplete(%s%s);' % (field_id, source, options)
def render(self, name, value=None, attrs=None):
final_attrs = self.build_attrs(attrs, name=name)
if value:
final_attrs['value'] = escape(smart_unicode(value))
if not self.attrs.has_key('id'):
final_attrs['id'] = 'id_%s' % name
return u'''<input type="text" %(attrs)s/>
<script type="text/javascript"><!--//
%(js)s//--></script>
''' % {
'attrs' : flatatt(final_attrs),
'js' : self.render_js(final_attrs['id']),
}
# views.py - sample view
from django.http import HttpResponse, HttpResponseBadRequest
from django.views.decorators.cache import cache_page
from apps.foo.models import Foo
def autocomplete(request):
def iter_results(results):
if results:
for r in results:
yield '%s|%s\n' % (r.name, r.id)
if not request.GET.get('q'):
return HttpResponse(mimetype='text/plain')
q = request.GET.get('q')
limit = request.GET.get('limit', 15)
try:
limit = int(limit)
except ValueError:
return HttpResponseBadRequest()
foos = Foo.objects.filter(name__startswith=q)[:limit]
return HttpResponse(iter_results(foos), mimetype='text/plain')
autocomplete = cache_page(autocomplete, 60 * 60)
|
More like this
- Template tag - list punctuation for a list of items by shapiromatron 10 months, 3 weeks ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 11 months 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, 7 months ago
Comments
Hi, I tried to use your widget, very usefull by the way, but it took me some time to realise that (line 53) the 'js' key should need the url matching with your 'autocomplete' view, right? In fact, I'm wondering how it works if you send a list of elements to self.source? Thanks for your reply!
#
The data returned from the view needs to have a linebreak after each entry.
So line 66 needs to be changed to:
#
thank you, now it is fixed
#
I had a problem with IE coughing on the <script> for registering the event handlers with jQuery. I changed line 38 to register den handlers on onLoad:
return u'$(function() {$(\'#%s\').autocomplete(%s%s);})' % (field_id, source, options)
#
I think lines 10 & 11 must be in __init__ method, because in the current state "attrs" is unsable.
Now this widget work like Singleton pattern and when we set "attrs" in one field, we get it in other fields too.
#
fixed
#
Has anyone a full working example to provide me (including urls.py, form definitions, etc) ? Because I can't make it work. I'm newbie to newforms so that may be the reason.
Thanks.
#
Hi. I like it alot :o) I can see this snippet is from 2007. My question is: does it work with Django ver 1.1 ?
#
@michaelh : not as is. e.g.
django.newforms
is now available as simplydjango.forms
I haven't try yet but have a peep at #1097
#
Please login first before commenting.