Login

MultiSelectField

Author:
steph
Posted:
March 5, 2012
Language:
Python
Version:
1.3
Score:
0 (after 0 ratings)

This field provides a multi select choice field.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# -*- coding: utf-8 -*-
from django import forms
from django.core.exceptions import ValidationError
from django.db import models
from django.utils.encoding import force_unicode
from django.utils.text import capfirst


class MultiSelectField(models.TextField):
    __metaclass__ = models.SubfieldBase

    def get_db_prep_value(self, value):
        if isinstance(value, basestring):
            return value
        elif isinstance(value, list):
            return ','.join(value)
        return ''

    def to_python(self, value):
        if isinstance(value, basestring):
            return value.split(',')
        elif isinstance(value, list):
            return value
        return ''

    def value_to_string(self, obj):
        # We need this to proper dump data.
        return self.get_db_prep_value(self._get_val_from_obj(obj))

    def get_choices_default(self):
        return self.get_choices(include_blank=False)

    def formfield(self, form_class=forms.MultipleChoiceField, **kwargs):
        # Using super() won't work because this would replace the form_class.
        defaults = {
            'required': not self.blank,
            'label': capfirst(self.verbose_name),
            'help_text': self.help_text,
            'choices': self.get_choices(include_blank=False),
        }
        if self.has_default():
            if callable(self.default):
                defaults['initial'] = self.default
                defaults['show_hidden_initial'] = True
            else:
                defaults['initial'] = self.get_default()
        defaults.update(kwargs)

        return form_class(**defaults)

    def validate(self, value, model_instance):
        if isinstance(value, list):
            valid_choices = [k for k, v in self.choices]
            for choice in value:
                if choice not in valid_choices:
                    raise ValidationError(
                        self.error_messages['invalid_choice'] % choice)

    def _get_display(field):
        def _inner(self):
            values = getattr(self, field.attname)
            return ', '.join([force_unicode(
                field.choices_dict.get(value, value),
                strings_only=True
            ) for value in values])
        return _inner

    def contribute_to_class(self, cls, name):
        self.set_attributes_from_name(name)
        self.model = cls
        cls._meta.add_field(self)
        self.choices_dict = dict(self.choices)
        setattr(cls, 'get_%s_display' % self.name, self._get_display())

More like this

  1. Template tag - list punctuation for a list of items by shapiromatron 10 months, 1 week ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 10 months, 2 weeks ago
  3. Serializer factory with Django Rest Framework by julio 1 year, 5 months ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 6 months ago
  5. Help text hyperlinks by sa2812 1 year, 6 months ago

Comments

Please login first before commenting.