diff options
Diffstat (limited to 'ishtar_common')
| -rw-r--r-- | ishtar_common/forms.py | 7 | ||||
| -rw-r--r-- | ishtar_common/models.py | 1 | ||||
| -rw-r--r-- | ishtar_common/models_common.py | 16 | ||||
| -rw-r--r-- | ishtar_common/widgets.py | 45 | 
4 files changed, 59 insertions, 10 deletions
diff --git a/ishtar_common/forms.py b/ishtar_common/forms.py index 31d1004c7..b92a80f42 100644 --- a/ishtar_common/forms.py +++ b/ishtar_common/forms.py @@ -136,6 +136,7 @@ JSON_VALUE_TYPES_FIELDS = {      "D": (DateField, None),      "B": (forms.NullBooleanField, None),      "C": (widgets.Select2DynamicField, None), +    "MC": (widgets.Select2DynamicMultipleField, None),  } @@ -312,8 +313,10 @@ class CustomForm(BSForm):                  attrs["help_text"] = field["help_text"]              if widget:                  attrs["widget"] = widget() -            if field_cls == widgets.Select2DynamicField: -                attrs["choices"] = cls._get_dynamic_choices(key) +            if field_cls in (widgets.Select2DynamicField, +                             widgets.Select2DynamicMultipleField): +                choices = cls._get_dynamic_choices(key) +                attrs["choices"] = choices              f = field_cls(**attrs)              kls = "form-control"              if "class" in f.widget.attrs: diff --git a/ishtar_common/models.py b/ishtar_common/models.py index 6da129adb..9c508c9fc 100644 --- a/ishtar_common/models.py +++ b/ishtar_common/models.py @@ -683,6 +683,7 @@ JSON_VALUE_TYPES = (      ("F", _("Float")),      ("D", _("Date")),      ("C", _("Choices")), +    ("MC", _("Multi-choices")),  ) diff --git a/ishtar_common/models_common.py b/ishtar_common/models_common.py index e67b78d67..b1c291bee 100644 --- a/ishtar_common/models_common.py +++ b/ishtar_common/models_common.py @@ -1077,12 +1077,22 @@ class JsonData(models.Model, CachedGen):          q = cls.objects.filter(data__has_key=key[len("data__") :]).values_list(              "data", flat=True          ) +        multi = False          for value in q.all():              for k in splitted_key:                  value = value[k] -            choices.add(value) -        choices = [("", "")] + [(v, v) for v in sorted(list(choices))] -        cache.set(cache_key, choices, settings.CACHE_SMALLTIMEOUT) +            if isinstance(value, list): +                multi = True +                for v in value: +                    if v: +                        choices.add(v) +            else: +                choices.add(value) +        c = [] +        if not multi: +            c = [("", "")] +        c += [(v, v) for v in sorted(list(choices))] +        cache.set(cache_key, c, settings.CACHE_SMALLTIMEOUT)          return choices diff --git a/ishtar_common/widgets.py b/ishtar_common/widgets.py index b80faee6d..efea07065 100644 --- a/ishtar_common/widgets.py +++ b/ishtar_common/widgets.py @@ -126,16 +126,23 @@ class Select2Media(object):          return media -class Select2Dynamic(Select2Media, forms.Select): +class Select2DynamicBase(Select2Media):      """      Select input using select, allowing dynamic creation.      """ +    MULTIPLE = False      def render(self, name, value, attrs=None, choices=()):          choices = choices or getattr(self, "choices", []) -        if value and value not in [key for key, v in choices]: -            choices.insert(1, (value, value)) -            self.choices = choices +        if value: +            values = [value] +            if self.MULTIPLE: +                value = value[0] +                values = value +            for va in values: +                if va not in [key for key, va in choices]: +                    choices.insert(1, (va, va)) +                    self.choices = choices          klass = attrs and attrs.get("class") or ""          klass += " " if klass else "" + "js-select2"          if not attrs: @@ -161,7 +168,9 @@ class Select2Dynamic(Select2Media, forms.Select):          if attrs.get("full-width", None):              options.append("containerCssClass: 'full-width'") -        html = super(Select2Dynamic, self).render(name, value, attrs) +        if self.MULTIPLE: +            options.append("multiple: 'true'") +        html = super(Select2DynamicBase, self).render(name, value, attrs)          html += """<script type="text/javascript">          $(document).ready(function() {{              $("#id_{}").select2({{ {} }}); @@ -172,6 +181,14 @@ class Select2Dynamic(Select2Media, forms.Select):          return mark_safe(html) +class Select2Dynamic(Select2DynamicBase, forms.Select): +    MULTIPLE = False + + +class Select2DynamicMultiple(Select2DynamicBase, forms.SelectMultiple): +    MULTIPLE = True + +  class Select2DynamicField(forms.ChoiceField):      widget = Select2Dynamic @@ -190,6 +207,24 @@ class Select2DynamicField(forms.ChoiceField):          return super(Select2DynamicField, self).to_python(value).strip() +class Select2DynamicMultipleField(forms.MultipleChoiceField): +    widget = Select2DynamicMultiple + +    def validate(self, value): +        """ +        Key can be added dynamically. Only check that the character " is not +        used. +        """ +        if value and '"' in value: +            raise ValidationError(_('The character " is not accepted.')) + +    def to_python(self, value): +        """ +        Strip value +        """ +        return [v.strip() for v in super().to_python(value)] + +  class Select2Base(Select2Media):      def __init__(          self, attrs=None, choices=(), remote=None, model=None, new=None, available=None  | 
