diff options
| author | Étienne Loks <etienne.loks@peacefrogs.net> | 2010-12-31 20:05:38 +0100 | 
|---|---|---|
| committer | Étienne Loks <etienne.loks@peacefrogs.net> | 2010-12-31 20:05:38 +0100 | 
| commit | cb791561a7668f1f21b0f28f46e6d85bda52ad37 (patch) | |
| tree | 7f9b04784c7a4334dcf502fc2a272866682e6cc9 | |
| parent | ef4a13bd49ea9afa286381bb11510efb1b0d76e9 (diff) | |
| download | Ishtar-cb791561a7668f1f21b0f28f46e6d85bda52ad37.tar.bz2 Ishtar-cb791561a7668f1f21b0f28f46e6d85bda52ad37.zip  | |
Better usage of AJAX autocomplete field
| -rw-r--r-- | ishtar/furnitures/forms.py | 9 | ||||
| -rw-r--r-- | ishtar/furnitures/models.py | 19 | ||||
| -rw-r--r-- | ishtar/furnitures/views.py | 5 | ||||
| -rw-r--r-- | ishtar/furnitures/widgets.py | 48 | ||||
| -rw-r--r-- | 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'''<input %(attrs)s/><p id="result"></p>
 +            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'''<input%(attrs_select)s/>\
 +<input type="hidden"%(attrs_hidden)s/>\
          <script type="text/javascript"><!--//
          $(function() {%(js)s});//--></script>
          ''' % {
 -            '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; +} +  | 
