使用jquery的AutocompleteWidget

[code]
from django.core.urlresolvers import reverse, NoReverseMatch
from django.newforms import HiddenInput, TextInput
from django.utils import simplejson
from django.utils.safestring import mark_safe

class AutocompleteWidget(TextInput):
"""
Autocomplete widget to use with jquery-autocomplete plugin.

Widget can use for static and dynamic (AJAX-liked) data. Also
you can relate some fields and it's values'll posted to autocomplete
view.

Widget support all jquery-autocomplete options that dumped to JavaScript
via django.utils.simplejson.

**Note** You must init one of ``choices`` or ``choices_url`` attribute.
Else widget raises TypeError when rendering.
"""
def __init__(self, attrs=None, choices=None, choices_url=None, options=None, related_fields=None):
"""
Optional arguments:
-------------------

* ``choices`` - Static autocomplete choices (similar to choices
used in Select widget).

* ``choices_url`` - Path to autocomplete view or autocomplete
url name.

* ``options`` - jQuery autocomplete plugin options. Auto dumped
to JavaScript via SimpleJSON

* ``related_fields`` - Fields that relates to current (value
of this field will sended to autocomplete view via POST)
"""
self.attrs = attrs or {}
self.choice, self.choices, self.choices_url = None, choices, choices_url
self.options = options or {}

if related_fields:
extra = {}
if isinstance(related_fields, str):
related_fields = list(related_fields)

for field in related_fields:
extra[field] = "%s_value" % field

self.extra = extra
else:
self.extra = {}

def render(self, name, value=None, attrs=None):
if not self.choices and not self.choices_url:
raise TypeError('One of "choices" or "choices_url" keyword argument must be supplied obligatory.')

if self.choices and self.choices_url:
raise TypeError('Only one of "choices" or "choices_url" keyword argument can be supplied.')

choices = ''

if self.choices:
self.set_current_choice(value)
choices = simplejson.dumps([unicode(v) for k, v in self.choices], ensure_ascii=False)
html_code = HiddenInput().render(name, value=value)
name += '_autocomplete'
else:
html_code = ''

if self.choices_url:
try:
choices = simplejson.dumps(reverse(str(self.choices_url)))
except NoReverseMatch:
choices = simplejson.dumps(self.choices_url)

if self.options or self.extra:
if 'extraParams' in self.options:
self.options['extraParams'].update(self.extra)
else:
self.options['extraParams'] = self.extra

options = ', ' + simplejson.dumps(self.options, indent=4, sort_keys=True)
extra = []

for k, v in self.extra.items():
options = options.replace(simplejson.dumps(v), v)
extra.append(u"function %s() { return $('#id_%s').val(); }\n" % (v, k))

extra = u''.join(extra)
else:
extra, options = '', ''

final_attrs = self.build_attrs(attrs)
html_code += super(AutocompleteWidget, self).render(name, self.choice or value, attrs)

html_code += u"""
<script type="text/javascript"><!--
%s$('#%s').autocomplete(%s%s);
--></script>
""" % (extra, final_attrs['id'], choices, options)

return mark_safe(html_code)

def set_current_choice(self, data):
if not self.choices:
raise ValueError('"choices" attribute was not defined yet.')

for k, v in self.choices:
if k == data:
self.choice = v
break

def value_from_datadict(self, data, files, name):
if not self.choices:
return super(AutocompleteWidget, self).value_from_datadict(data, files, name)

autocomplete_name = name + '_autocomplete'

if not autocomplete_name in data:
self.set_current_choice(data[name])
return data[name]

for k, v in self.choices:
if v == data[autocomplete_name]:
self.set_current_choice(k)
return k
[/code]
[code]
<strong>forms.py</strong>
from django import newforms as forms
from django.utils.translation import ugettext as _

from myproject.widgets import AutocompleteWidget

SPORTS_CHOICES = (
('basketball', _('Basketball')),
('football', _('Football')),
('hockey', _('Hockey')),
)

class SampleForm(forms.Form):
name = forms.CharField(label=_('Name'))
country = forms.CharField(label=_('Country'),
widget=AutocompleteWidget(choices_url='autocomplete_countries', related_fields=('city',)))
city = forms.CharField(label=_('City),
widget=AutocompleteWidget(choices_url='autocomplete_cities', related_fields=('country',)))
sports = forms.ChoiceField(label=_('Sports'), choices=SPORTS_CHOICES,
widget=AutocompleteWidget(options={'minChars': 0, 'autoFill': True, 'mustMatch': True}))

<strong>urls.py</strong>
from django.conf.urls.defaults import *

urlpatterns = patterns('',
url('/path/to/cities/autocomplete/', 'views.autocomplete_cities', name='autocomplete_cities'),
url('/path/to/countries/autocomplete/', 'views.autocomplete_countries', name='autocomplete_countries'),
)

<strong>views.py</strong>
from myproject.models import City

def autocomplete_cities(request):
def results_to_string(results):
if results:
for r in results:
yield '%s|%s\n' % (r.name, r.pk)

city = request.REQUEST.get('q', None)
country = request.REQUEST.get('country', None)

if city:
cities = City.objects.filter(city__istartswith=city)
else:
cities = City.objects.all()

if country:
cities = cities.filter(country__name=country)

cities = cities[:int(request.REQUEST.get('limit', 15))]
return results_to_string(cities, mimetype='text/plain')

[/code]
http://djangonaut.blogspot.com/2008/05/jquery-autocompletewidget-django.html
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值