diff options
Diffstat (limited to 'ishtar_common/widgets.py')
| -rw-r--r-- | ishtar_common/widgets.py | 144 | 
1 files changed, 102 insertions, 42 deletions
| diff --git a/ishtar_common/widgets.py b/ishtar_common/widgets.py index 42a93ddaa..4efb4c3fb 100644 --- a/ishtar_common/widgets.py +++ b/ishtar_common/widgets.py @@ -26,15 +26,16 @@ from django.conf import settings  from django.core.urlresolvers import reverse, NoReverseMatch  from django.db.models import fields  from django.forms import ClearableFileInput -from django.forms.widgets import flatatt, \ -    CheckboxSelectMultiple as CheckboxSelectMultipleBase -from django.template import Context, loader +from django.forms.utils import flatatt +from django.forms.widgets import CheckboxSelectMultiple as \ +    CheckboxSelectMultipleBase +from django.template import loader  from django.template.defaultfilters import slugify  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 +from json import JSONEncoder  from django.utils.translation import ugettext_lazy as _  from ishtar_common import models @@ -44,6 +45,61 @@ logger = logging.getLogger(__name__)  reverse_lazy = lazy(reverse, unicode) +class SelectReadonly(forms.Select): +    template_name = 'blocks/readonly_input.html' +    option_template_name = 'blocks/readonly_input_option.html' + +    def __init__(self, attrs=None, choices=(), model=None, available=None): +        super(SelectReadonly, self).__init__(attrs, choices) +        self.available = available +        self.model = model + +    def get_choices(self, value): +        q = self.model.objects +        if self.available: +            q = q.filter(available=True) +        if value: +            q = q.filter(pk=value) +        for i in q.all(): +            if hasattr(self.model, 'verbose_name'): +                label = i.verbose_name +            else: +                label = unicode(i) +            yield (i.pk, label) + +    def render(self, name, value, attrs=None, choices=()): +        if value: +            self.choices = list(self.get_choices(value)) +            value = self.choices[0][0] +        return super(SelectReadonly, self).render(name, value, attrs) + + +class SelectReadonlyField(forms.ChoiceField): +    def __init__(self, choices=(), required=True, widget=None, label=None, +                 initial=None, help_text='', *args, **kwargs): +        self.available = False +        self.model = None +        if 'model' in kwargs: +            self.model = kwargs.pop('model') +        if 'available' in kwargs: +            self.available = kwargs.pop('available') +        widget = SelectReadonly(model=self.model, available=self.available) +        super(SelectReadonlyField, self).__init__( +            choices, required, widget, label, initial, help_text, *args, +            **kwargs) + +    def get_q(self): +        q = self.model.objects +        if self.available: +            q = q.filter(available=True) +        return q + +    def valid_value(self, value): +        if not self.model: +            return super(SelectReadonlyField, self).valid_value(value) +        return bool(self.get_q().filter(pk=value).count()) + +  class Select2Multiple(forms.SelectMultiple):      def __init__(self, attrs=None, choices=(), remote=None, model=None,                   available=None): @@ -80,8 +136,11 @@ class Select2Multiple(forms.SelectMultiple):          if self.remote in ('None', 'false'):              # test on lazy object is buggy... so we have this ugly test              self.remote = None -        if not choices and not self.remote and self.model: -            choices = self.get_choices() +        if not choices: +            if not self.remote and self.model: +                choices = self.get_choices() +            if hasattr(self, 'choices') and self.choices: +                choices = self.choices          new_attrs = self.attrs.copy()          new_attrs.update(attrs)          attrs = new_attrs @@ -134,8 +193,8 @@ class Select2Multiple(forms.SelectMultiple):              else:                  options = "{"              options += "     containerCssClass: 'full-width'}" -        html = super(Select2Multiple, self).render(name, value, attrs, -                                                   choices) +        self.choices = choices +        html = super(Select2Multiple, self).render(name, value, attrs)          html += """<script type="text/javascript">          $(document).ready(function() {{              $("#id_{}").select2({}); @@ -155,8 +214,7 @@ class CheckboxSelectMultiple(CheckboxSelectMultipleBase):              value = value.split(',')          if type(value) not in (list, tuple):              value = [value] -        return super(CheckboxSelectMultiple, self).render(name, value, attrs, -                                                          choices) +        return super(CheckboxSelectMultiple, self).render(name, value, attrs)  class Select2MultipleField(forms.MultipleChoiceField): @@ -191,9 +249,9 @@ class Select2MultipleField(forms.MultipleChoiceField):  class DeleteWidget(forms.CheckboxInput): -    def render(self, name, value, attrs=None): -        final_attrs = flatatt(self.build_attrs(attrs, name=name, -                                               value='1')) +    def render(self, name, value, attrs=None, renderer=None): +        final_attrs = flatatt( +            self.build_attrs(attrs, {"name": name, "value": '1'}))          output = ['<tr class="delete"><td colspan="2">']          output.append(u"<button%s>%s</button>" % (final_attrs, _("Delete")))          output.append('</td></tr>') @@ -206,16 +264,17 @@ class ImageFileInput(ClearableFileInput):  class SquareMeterWidget(forms.TextInput): -    def render(self, name, value, attrs=None): +    def render(self, name, value, attrs=None, renderer=None):          if not value:              value = u"" -        final_attrs = flatatt(self.build_attrs(attrs, name=name, value=value)) +        final_attrs = flatatt( +            self.build_attrs(attrs, {"name": name, "value": value}))          dct = {'final_attrs': final_attrs,                 'unit': settings.SURFACE_UNIT_LABEL,                 'id': attrs['id'],                 "safe_id": attrs['id'].replace('-', '_')}          t = loader.get_template('blocks/SquareMeterWidget.html') -        rendered = t.render(Context(dct)) +        rendered = t.render(dct)          return mark_safe(rendered)  AreaWidget = forms.TextInput @@ -231,7 +290,7 @@ class JQueryDate(forms.TextInput):              self.attrs['class'] = ''          self.attrs['class'] = 'date-pickup' -    def render(self, name, value=None, attrs=None): +    def render(self, name, value, attrs=None, renderer=None):          if value:              value = unicode(value)          # very specific... @@ -266,25 +325,29 @@ class JQueryDate(forms.TextInput):  class JQueryAutoComplete(forms.TextInput): -    def __init__(self, source, associated_model=None, options={}, attrs={}, -                 new=False, url_new='', multiple=False, limit={}, -                 dynamic_limit=[]): +    def __init__(self, source, associated_model=None, options=None, attrs=None, +                 new=False, url_new='', multiple=False, limit=None, +                 dynamic_limit=None):          """          Source can be a list containing the autocomplete values or a          string containing the url used for the request.          """ -        self.options = None -        self.attrs = {}          self.source = source          self.associated_model = associated_model -        if len(options) > 0: + +        self.options = None +        if options and len(options) > 0:              self.options = JSONEncoder().encode(options) -        self.attrs.update(attrs) +        self.attrs = {} + +        if attrs: +            self.attrs.update(attrs) +          self.new = new          self.url_new = url_new          self.multiple = multiple -        self.limit = limit -        self.dynamic_limit = dynamic_limit +        self.limit = limit or {} +        self.dynamic_limit = dynamic_limit or []      def value_from_datadict(self, data, files, name):          if self.multiple: @@ -313,22 +376,20 @@ class JQueryAutoComplete(forms.TextInput):          if self.options:              dct['options'] = mark_safe('%s' % self.options) -        js = ""          tpl = 'blocks/JQueryAutocomplete.js'          if self.multiple:              tpl = 'blocks/JQueryAutocompleteMultiple.js'          t = loader.get_template(tpl) -        js = t.render(Context(dct)) +        js = t.render(dct)          return js -    def render(self, name, value=None, attrs=None): -        attrs_hidden = self.build_attrs(attrs, name=name) +    def render(self, name, value, attrs=None, renderer=None): +        attrs_hidden = self.build_attrs(attrs, {"name": name})          attrs_select = self.build_attrs(attrs)          attrs_select['placeholder'] = _(u"Search...")          if value:              hiddens = []              selects = [] -            values = value              if type(value) not in (list, tuple):                  values = unicode(escape(smart_unicode(value)))                  values = values.replace('[', '').replace(']', '') @@ -428,8 +489,8 @@ class JQueryTown(forms.TextInput):                  raise ValueError('source type is not valid')          return encoded_src -    def render(self, name, value=None, attrs=None): -        attrs_hidden = self.build_attrs(attrs, name=name) +    def render(self, name, value, attrs=None, renderer=None): +        attrs_hidden = self.build_attrs(attrs, {"name": name})          attrs_select = self.build_attrs(attrs)          attrs_select['placeholder'] = _(u"Search...")          selected = '' @@ -487,7 +548,7 @@ class JQueryTown(forms.TextInput):                      'selected_state': selected_state}                     )          html = loader.get_template('blocks/JQueryAdvancedTown.html')\ -                     .render(Context(dct)) +                     .render(dct)          return html @@ -540,11 +601,11 @@ class JQueryPersonOrganization(forms.TextInput):                 'field_id': field_id}          if self.options:              dct['options'] = mark_safe('%s' % self.options) -        js = loader.get_template(self.js_template).render(Context(dct)) +        js = loader.get_template(self.js_template).render(dct)          return js -    def render(self, name, value=None, attrs=None): -        attrs_hidden = self.build_attrs(attrs, name=name) +    def render(self, name, value, attrs=None, renderer=None): +        attrs_hidden = self.build_attrs(attrs, {'name': name})          attrs_select = self.build_attrs(attrs)          attrs_select['placeholder'] = _(u"Search...")          selected = '' @@ -586,7 +647,7 @@ class JQueryPersonOrganization(forms.TextInput):                 'name': name,                 'js': self.render_js(name, selected),                 'new': mark_safe(new)} -        html = loader.get_template(self.html_template).render(Context(dct)) +        html = loader.get_template(self.html_template).render(dct)          return html @@ -692,11 +753,10 @@ class JQueryJqGrid(forms.RadioSelect):              extra_cols = extra_cols and ", ".join(extra_cols) or ""          return jq_col_names, extra_cols -    def render(self, name, value=None, attrs=None): +    def render(self, name, value, attrs=None, renderer=None):          t = loader.get_template('blocks/form_flex_snippet.html')          form = self.form() -        rendered = t.render(Context({'form': form, -                                     'flex': True})) +        rendered = t.render({'form': form, 'flex': True})          dct = {}          if self.new:              model_name = self.associated_model._meta.object_name.lower() @@ -744,5 +804,5 @@ class JQueryJqGrid(forms.RadioSelect):                      'multi_cols': ",".join((u'"%d"' % col                                             for col in self.multiple_cols))})          t = loader.get_template('blocks/JQueryJqGrid.html') -        rendered += t.render(Context(dct)) +        rendered += t.render(dct)          return mark_safe(rendered) | 
