From cb791561a7668f1f21b0f28f46e6d85bda52ad37 Mon Sep 17 00:00:00 2001 From: Étienne Loks Date: Fri, 31 Dec 2010 20:05:38 +0100 Subject: Better usage of AJAX autocomplete field --- ishtar/furnitures/forms.py | 9 ++++++--- ishtar/furnitures/models.py | 19 ++++++++++++++++-- ishtar/furnitures/views.py | 5 ++--- ishtar/furnitures/widgets.py | 48 ++++++++++++++++++++++++++++++-------------- static/media/style.css | 9 +++++++++ 5 files changed, 67 insertions(+), 23 deletions(-) diff --git a/ishtar/furnitures/forms.py b/ishtar/furnitures/forms.py index 367e97cb1..7f9347197 100644 --- a/ishtar/furnitures/forms.py +++ b/ishtar/furnitures/forms.py @@ -68,7 +68,9 @@ class FileWizard(Wizard): class FileForm1(forms.Form): in_charge = forms.IntegerField(label=_("Person in charge"), - widget=widgets.JQueryAutoComplete(reverse_lazy('autocomplete-person'))) + widget=widgets.JQueryAutoComplete(reverse_lazy('autocomplete-person'), + associated_model=models.Person), + validators=[models.Person.valid_id]) year = forms.IntegerField(label=_("Year"), initial=lambda:datetime.datetime.now().year) internal_reference = forms.CharField(label=_(u"Internal reference"), @@ -76,8 +78,9 @@ class FileForm1(forms.Form): creation_date = forms.DateField(label=_(u"Creation date"), initial=datetime.datetime.now) file_type = forms.ChoiceField(label=_("File type"), - choices=models.FileType.objects.filter(available=True)) - comment = forms.CharField(label=_(u"Comment"), widget=forms.Textarea) + choices=models.FileType.get_types()) + comment = forms.CharField(label=_(u"Comment"), widget=forms.Textarea, + required=False) class FileForm2(forms.Form): diff --git a/ishtar/furnitures/models.py b/ishtar/furnitures/models.py index d3b942102..28420118b 100644 --- a/ishtar/furnitures/models.py +++ b/ishtar/furnitures/models.py @@ -22,7 +22,8 @@ Models description """ import datetime -from django.core.exceptions import ObjectDoesNotExist +from django.core.exceptions import ObjectDoesNotExist, ValidationError +from django.core.validators import validate_slug from django.utils.translation import ugettext_lazy as _, ugettext from django.contrib.auth.models import User @@ -45,6 +46,8 @@ class GeneralType(models.Model): Abstract class for "types" """ label = models.CharField(_(u"Label"), max_length=100) + txt_idx = models.CharField(_(u"Textual identifier"), + validators=[validate_slug], max_length=30, unique=True) comment = models.TextField(_(u"Comment"), blank=True, null=True) available = models.BooleanField(_(u"Available")) @@ -54,6 +57,11 @@ class GeneralType(models.Model): def __unicode__(self): return self.label + @classmethod + def get_types(cls): + for item in cls.objects.filter(available=True).all(): + yield (item.id, _(item.label)) + class BaseHistorizedItem(models.Model): history_modifier = models.ForeignKey(User, related_name='+', verbose_name=_(u"Last modifier")) @@ -156,7 +164,14 @@ class Person(Address, OwnPerms) : ) def __unicode__(self): - return u"%s %s" % (self.name, self.surname) + return u"%s %s - %s" % (self.name, self.surname, self.email) + + @classmethod + def valid_id(cls, value): + try: + cls.objects.get(pk=value) + except ObjectDoesNotExist: + raise ValidationError(_(u"Not a valid person.")) class IshtarUser(models.Model): user = models.ForeignKey(User, unique=True, related_name='profile', diff --git a/ishtar/furnitures/views.py b/ishtar/furnitures/views.py index f9157d9d6..995eafea9 100644 --- a/ishtar/furnitures/views.py +++ b/ishtar/furnitures/views.py @@ -63,9 +63,8 @@ def autocomplete_person(request): query = query | Q(name__istartswith=q) | Q(surname__istartswith=q) | \ Q(email__icontains=q) persons = models.Person.objects.filter(query)[:limit] - data = json.dumps([{'id':person.pk, - 'value':"%s %s - %s" % (person.name, person.surname, person.email)} - for person in persons]) + data = json.dumps([{'id':person.pk, 'value':unicode(person)} + for person in persons]) return HttpResponse(data, mimetype='text/plain') def action(request, action_slug, obj_id=None, *args, **kwargs): diff --git a/ishtar/furnitures/widgets.py b/ishtar/furnitures/widgets.py index bbcb58423..fd9077b5e 100644 --- a/ishtar/furnitures/widgets.py +++ b/ishtar/furnitures/widgets.py @@ -23,9 +23,10 @@ from django.forms.widgets import flatatt from django.utils.encoding import smart_unicode from django.utils.html import escape from django.utils.simplejson import JSONEncoder +from django.core.urlresolvers import resolve class JQueryAutoComplete(forms.TextInput): - def __init__(self, source, options={}, attrs={}): + def __init__(self, source, associated_model=None, options={}, attrs={}): """ Source can be a list containing the autocomplete values or a string containing the url used for the request. @@ -33,6 +34,7 @@ class JQueryAutoComplete(forms.TextInput): self.options = None self.attrs = {} self.source = source + self.associated_model = associated_model if len(options) > 0: self.options = JSONEncoder().encode(options) self.attrs.update(attrs) @@ -49,29 +51,45 @@ class JQueryAutoComplete(forms.TextInput): raise ValueError('source type is not valid') options = 'source : ' + source options += ''', select: function( event, ui ) { - $("#result").html(ui.item ? - "Selected: " + ui.item.value + " aka " + ui.item.id : - "Nothing selected, input was " + this.value ); - },minLength: 2 - - ''' + if(ui.item){ + $('#id_%s').val(ui.item.id); + } else { + $('#id_%s').val(null); + } + }, minLength: 2 + ''' % (field_id, field_id) if self.options: options += ',%s' % self.options - return u'$(\'#%s\').autocomplete({%s});' % (field_id, options) + js = u'$(\'#id_select_%s\').autocomplete({%s});\n' % (field_id, options) + return js 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)) + attrs_hidden = self.build_attrs(attrs, name=name) + attrs_select = self.build_attrs(attrs) + if value: + val = escape(smart_unicode(value)) + attrs_hidden['value'] = val + attrs_select['value'] = val + if self.associated_model: + try: + attrs_select['value'] = unicode(self.associated_model.\ +objects.get(pk=value)) + except: + attrs_select['value'] = "" if not self.attrs.has_key('id'): - final_attrs['id'] = 'id_%s' % name - return u'''

+ attrs_hidden['id'] = 'id_%s' % name + attrs_select['id'] = 'id_select_%s' % name + if 'class' not in attrs_select: + attrs_select['class'] = 'autocomplete' + return u'''\ +\ ''' % { - 'attrs' : flatatt(final_attrs), - 'js' : self.render_js(final_attrs['id']), + 'attrs_select' : flatatt(attrs_select), + 'attrs_hidden' : flatatt(attrs_hidden), + 'js' : self.render_js(name), } diff --git a/static/media/style.css b/static/media/style.css index c8f24857c..5caaa1353 100644 --- a/static/media/style.css +++ b/static/media/style.css @@ -24,6 +24,10 @@ label:first-letter { text-transform: uppercase; } +td{ + text-align:left; +} + .hidden{ display:none; } @@ -138,3 +142,8 @@ div.form table th{ padding:0; margin:0.2em; } + +.autocomplete{ + width:300px; +} + -- cgit v1.2.3