#----------------------- widgets.py------------------------ # -*- coding: utf-8 -*- # # In order to use this widget you need: # 1. download YUI library and put it in # your MEDIA folder (http://developer.yahoo.com/yui/) # 2. Include necessary js and css imports at your page # Check for necessary imports at 'YUI autocomplete' page # My imports are visible at test_ajax.html # 3. Assign a widget to field (with schema and lookup_url parameters) # 4. Define view to do a data lookup for ajax queries # from django import newforms as forms from django.utils.safestring import mark_safe from django.utils.encoding import force_unicode #AUTOCOMPLETE AC_SNIPPET = """ <div class="ac_container"> <input %s /> <div id="%s_container" class="yui-skin-sam"></div> <script type="text/javascript"> // An XHR DataSource var acServer_%s = "%s"; var acSchema_%s = %s; var acDataSource_%s = new YAHOO.widget.DS_XHR(acServer_%s, acSchema_%s); var acAutoComp_%s = new YAHOO.widget.AutoComplete("%s","%s_container", acDataSource_%s); acAutoComp_%s.useIFrame = true; acAutoComp_%s.animSpeed = 0; %s %s </script> </div> """ def_format_result = 'acAutoComp_%s.formatResult = %s;' def_item_select_handler = 'acAutoComp_%s.itemSelectEvent.subscribe(%s);' class AutoCompleteWidget(forms.widgets.TextInput): """ widget autocomplete for text fields """ def __init__(self, schema=None, lookup_url=None, format_result_fname='', item_select_handler_fname='', *args, **kw): super(AutoCompleteWidget, self).__init__(*args, **kw) # YUI schema self.schema = schema # url for YUI XHR Datasource self.lookup_url = lookup_url # optional name of javascript function that formats results (YUI) self.format_result_fname = format_result_fname # optional name of javascript function that handles item select event (YUI) self.item_select_handler_fname = item_select_handler_fname def render(self, name, value, attrs=None): html_id = attrs.get('id', name) # url for YUI XHR Datasource lookup_url = self.lookup_url # YUI schema schema = self.schema # optional name of javascript function that handles item select event (YUI) item_select_handler_fname = getattr(self, 'item_select_handler_fname', '') # optional name of javascript function that formats results (YUI) format_result_fname = getattr(self, 'format_result_fname', '') if value is None: value = '' final_attrs = self.build_attrs(attrs, type=self.input_type, name=name) if value != '': final_attrs['value'] = force_unicode(value) # Only add the 'value' attribute if a value is non-empty. final_attrs['class'] = 'autocomplete_widget' fr = '' # format result sh = '' # select handler if self.format_result_fname: fr = def_format_result % (html_id, self.format_result_fname) if self.item_select_handler_fname: sh = def_item_select_handler % (html_id, self.item_select_handler_fname) return mark_safe(AC_SNIPPET % (forms.util.flatatt(final_attrs), html_id, html_id, lookup_url,html_id, schema, html_id, html_id, html_id, html_id, html_id, html_id, html_id,html_id, html_id, fr, sh)) #/AUTOCOMPLETE #/----------------------- widgets.py------------------------ # #EXAMPLE APPLICATION: --------------------------------------- # # code below is a listing of files from example application # that uses AutocompleteWidget, you don't have to create these # files! Only thing you need to put into your application # is code from above: widgets.py #----------------------- test_ajax.html ------------------- <html> <head> <!-- yui --> <link rel="stylesheet" type="text/css" href="{{ MEDIA_URL }}base/js/yui/assets/skins/sam/autocomplete.css" /> <script type="text/javascript" src="{{ MEDIA_URL }}base/js/yui/utilities/utilities.js"></script> <script type="text/javascript" src="{{ MEDIA_URL }}base/js/yui/autocomplete/autocomplete-min.js"></script> <script type="text/javascript" src="{{ MEDIA_URL }}base/js/yui/datasource/datasource-beta-min.js"></script> <!-- /yui--> </head> <body> <div class="yui-skin-sam"> <form> {{ user_form.as_p }} </form> </div> </body> </html> #/----------------------- test_ajax.html ------------------- #----------------------- views.py------------------------ # -*- coding: utf-8 -*- from <SOMEWHERE: http://www.djangosnippets.org/snippets/154/> import JsonResponse from django.contrib.auth.models import User from django.template import RequestContext import django.db.models from django.shortcuts import render_to_response from django import newforms as forms from widgets import AutoCompleteWidget def test_ajax_ac(request): """ returns data displayed at autocomplete list - this function is accessed by AJAX calls """ limit = 10 query = request.GET.get('query', None) qargs = [] # it is up to you how query looks if query: qargs = [django.db.models.Q(first_name__startswith=query) | \ django.db.models.Q(last_name__startswith=query) | \ django.db.models.Q(email__startswith=query)] users = User.objects.filter(django.db.models.Q(*qargs)).order_by('first_name')[:limit] results = [] for user in users: results.append({'id':user.pk, 'name':user.get_full_name(), 'email':user.email}) ret_dict = {'resultset':{'totalResultsReturned':len(results), 'results':results}} return JsonResponse(ret_dict) class UserForm(forms.Form): username = forms.CharField(max_length=100) def __init__(self, *args, **kwargs): super(UserForm, self).__init__(*args, **kwargs) n_lookup_url = reverse('test_ajax_ac') n_schema = '["resultset.results", "name", "email"]' self.fields['username'].widget = \ AutoCompleteWidget(lookup_url = n_lookup_url, schema = n_schema) def test_ajax(request): """ Displays user form """ user_form = UserForm() return render_to_response('test_ajax.html', {'user_form':user_form}, context_instance=RequestContext(request)) #/----------------------- views.py------------------------ #------------------------ urls.py------------------------- from django.conf.urls.defaults import * from django.conf import settings urlpatterns = patterns('views', url(r'^test_ajax/$', 'test_ajax', name='test_ajax'), url(r'^test_ajax_ac/$', 'test_ajax_ac', name='test_ajax_ac'), ) #/------------------------ urls.py-------------------------