Login

jquery autocomplete widget

Author:
skam
Posted:
May 13, 2007
Language:
Python
Version:
.96
Score:
25 (after 25 ratings)

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

  1. Template tag - list punctuation for a list of items by shapiromatron 2 months ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 2 months, 1 week ago
  3. Serializer factory with Django Rest Framework by julio 9 months, 1 week ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 9 months, 4 weeks ago
  5. Help text hyperlinks by sa2812 10 months, 3 weeks ago

Comments

seb (on May 16, 2007):

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!

#

slypheed (on May 23, 2007):

The data returned from the view needs to have a linebreak after each entry.

So line 66 needs to be changed to:

            yield '%s|%s\n' % (r.name, r.id)

#

skam (on June 1, 2007):

thank you, now it is fixed

#

Lau (on June 6, 2007):

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)

#

oxyum (on February 6, 2008):

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.

#

skam (on February 11, 2008):

fixed

#

jeje (on October 24, 2008):

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.

#

michaelh (on August 20, 2009):

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 ?

#

romain-hardouin (on October 28, 2009):

@michaelh : not as is. e.g. django.newforms is now available as simply django.forms

I haven't try yet but have a peep at #1097

#

Please login first before commenting.