diff options
author | Étienne Loks <etienne.loks@peacefrogs.net> | 2013-12-26 19:09:09 +0100 |
---|---|---|
committer | Étienne Loks <etienne.loks@peacefrogs.net> | 2013-12-26 19:09:09 +0100 |
commit | 39e296ed421cce7696313dcafe75cd03d073054d (patch) | |
tree | d69858ce6408508fc2661a04e75d0a5b32d33f5a /ishtar_common/widgets.py | |
parent | bd64ebef333c1275923bf90dd69e8181e80092aa (diff) | |
download | Ishtar-39e296ed421cce7696313dcafe75cd03d073054d.tar.bz2 Ishtar-39e296ed421cce7696313dcafe75cd03d073054d.zip |
Manage archaeological sites into forms (refs #1586)
* create new widget: multiple autocomplete field
* move JS autocomplete to template
* archaeological site reference made unique
Diffstat (limited to 'ishtar_common/widgets.py')
-rw-r--r-- | ishtar_common/widgets.py | 113 |
1 files changed, 87 insertions, 26 deletions
diff --git a/ishtar_common/widgets.py b/ishtar_common/widgets.py index a97cfe70b..fc3ada283 100644 --- a/ishtar_common/widgets.py +++ b/ishtar_common/widgets.py @@ -27,6 +27,7 @@ from django.forms import ClearableFileInput from django.forms.widgets import flatatt
from django.template import Context, loader
from django.utils.encoding import smart_unicode
+from django.utils.functional import lazy
from django.utils.html import escape
from django.utils.safestring import mark_safe
from django.utils.simplejson import JSONEncoder
@@ -34,6 +35,44 @@ from django.utils.translation import ugettext_lazy as _ import models
+reverse_lazy = lazy(reverse, unicode)
+
+class MultipleAutocompleteField(forms.MultipleChoiceField):
+ def __init__(self, *args, **kwargs):
+ model = None
+ if 'model' in kwargs:
+ model = kwargs.pop('model')
+ if 'choices' not in kwargs and model:
+ kwargs['choices'] = [(i.pk, unicode(i))for i in model.objects.all()]
+ new = kwargs.pop('new') if 'new' in kwargs else None
+ if 'widget' not in kwargs and model:
+ kwargs['widget'] = JQueryAutoComplete(reverse_lazy(
+ 'autocomplete-'+model.__name__.lower()),
+ associated_model=model, new=new,
+ multiple=True)
+ super(MultipleAutocompleteField, self).__init__(*args, **kwargs)
+
+ def clean(self, value):
+ if value:
+ # clean JS messup with values
+ try:
+ if type(value) not in (list, tuple):
+ value = [value]
+ else:
+ val = value
+ value = []
+ for v in val:
+ v = unicode(v).strip('[').strip(']'
+ ).strip('u').strip("'").strip('"')
+ value += [int(v.strip())
+ for v in list(set(v.split(',')))
+ if v.strip()]
+ except (TypeError, ValueError):
+ value = []
+ else:
+ value = []
+ return super(MultipleAutocompleteField, self).clean(value)
+
class DeleteWidget(forms.CheckboxInput):
def render(self, name, value, attrs=None):
final_attrs = flatatt(self.build_attrs(attrs, name=name,
@@ -95,7 +134,7 @@ class JQueryDate(forms.TextInput): class JQueryAutoComplete(forms.TextInput):
def __init__(self, source, associated_model=None, options={}, attrs={},
- new=False):
+ new=False, multiple=False):
"""
Source can be a list containing the autocomplete values or a
string containing the url used for the request.
@@ -108,6 +147,13 @@ class JQueryAutoComplete(forms.TextInput): self.options = JSONEncoder().encode(options)
self.attrs.update(attrs)
self.new = new
+ self.multiple = multiple
+
+ def value_from_datadict(self, data, files, name):
+ if self.multiple:
+ return data.getlist(name, None)
+ else:
+ return data.get(name, None)
def render_js(self, field_id):
if isinstance(self.source, list):
@@ -119,39 +165,54 @@ class JQueryAutoComplete(forms.TextInput): source = "'" + unicode(self.source) + "'"
except:
raise ValueError('source type is not valid')
- options = 'source : ' + source
- options += ''', select: function( event, ui ) {
- if(ui.item){
- $('#id_%s').val(ui.item.id);
- } else {
- $('#id_%s').val(null);
- }
- }, minLength: 2
- ''' % (field_id, field_id)
+ dct = {'source':mark_safe(source),
+ 'field_id':field_id}
if self.options:
- options += ',%s' % self.options
+ dct['options'] = mark_safe('%s' % self.options)
- js = u'$(\'#id_select_%s\').autocomplete({%s});\n' % (field_id, options)
- js += u'''$(\'#id_select_%s\').live('click', function(){
- $('#id_%s').val(null);
- $('#id_select_%s').val(null);
-});''' % (field_id, field_id, field_id)
+ js = ""
+ tpl = 'blocks/JQueryAutocomplete.js'
+ if self.multiple:
+ tpl = 'blocks/JQueryAutocompleteMultiple.js'
+ t = loader.get_template(tpl)
+ js = t.render(Context(dct))
return js
def render(self, name, value=None, attrs=None):
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'] = ""
+ hiddens = []
+ selects = []
+ values = value
+ if type(value) not in (list, tuple):
+ values = unicode(escape(smart_unicode(value)))
+ values = values.replace('[', '').replace(']', '')
+ values = values.split(',')
+ else:
+ values = []
+ for v in value:
+ values += v.split(',')
+ for v in values:
+ if not v:
+ continue
+ hiddens.append(v)
+ selects.append(v)
+ if self.associated_model:
+ try:
+ selects[-1] = unicode(
+ self.associated_model.objects.get(pk=v))
+ except (self.associated_model.DoesNotExist, ValueError):
+ selects.pop()
+ hiddens.pop()
+ if self.multiple:
+ attrs_hidden['value'] = ", ".join(hiddens)
+ if selects:
+ selects.append("")
+ attrs_select['value'] = ", ".join(selects)
+ else:
+ attrs_hidden['value'] = hiddens[0]
+ attrs_select['value'] = selects[0]
if not self.attrs.has_key('id'):
attrs_hidden['id'] = 'id_%s' % name
attrs_select['id'] = 'id_select_%s' % name
|