Skip to content

Instantly share code, notes, and snippets.



Created Aug 22, 2016
What would you like to do?
MultipleSelectField Django 1.10 Python 3.4
from django import forms
from django.core import exceptions
from django.db import models
from django.utils.encoding import force_text
class MultipleSelectFormField(forms.MultipleChoiceField):
widget = forms.CheckboxSelectMultiple
class MultipleSelectField(models.Field):
def get_internal_type(self):
return 'CharField'
def get_choices_default(self):
return self.get_choices(include_blank=False)
def formfield(self, **kwargs):
# don't call super, as that overrides default widget if it has choices
defaults = {
'required': not self.blank,
'label': self.verbose_name.capitalize(),
'help_text': self.help_text,
'choices': self.choices
if self.has_default():
defaults['initial'] = self.get_default()
return MultipleSelectFormField(**defaults)
def get_db_prep_value(self, value, connection, prepared=False):
if isinstance(value, list):
return ','.join(map(str, value))
if value is None or isinstance(value, str):
return value
return str(value)
def from_db_value(self, value, expression, connection, context):
return str(value).split(',')
def to_python(self, value):
if value is None or isinstance(value, list):
return value
return str(value).split(',')
def validate(self, value, model_instance):
if not self.editable:
# Skip validation for non-editable fields.
if self.choices and value not in self.empty_values:
if not isinstance(value, list):
value = [value]
if set(dict(self.choices).keys()) & set(value) == set(value):
raise exceptions.ValidationError(
params={'value': value},
if value is None and not self.null:
raise exceptions.ValidationError(
self.error_messages['null'], code='null')
if not self.blank and value in self.empty_values:
raise exceptions.ValidationError(
self.error_messages['blank'], code='blank')
def contribute_to_class(self, cls, name, virtual_only=False):
super(MultipleSelectField, self).contribute_to_class(cls, name)
if self.choices:
fieldname =
choicedict = dict(self.choices)
def func(self):
value = getattr(self, fieldname)
if not isinstance(value, list):
value = [value]
return ', '.join([force_text(choicedict.get(i, i))
for i in value])
setattr(cls, 'get_%s_display' % fieldname, func)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment