This article describes how to use a django custom Field to store strings separated by commas (,). For more information about how to store strings separated by commas (,) in a Field, see, returns a list.
The code is as follows:
From django import forms
From django. db import models
From django. utils. text import capfirst
From django. core import exceptions
Class MultiSelectFormField (forms. MultipleChoiceField ):
Widget = forms. CheckboxSelectMultiple
Def _ init _ (self, * args, ** kwargs ):
Self. max_choices = kwargs. pop ('max _ choices', 0)
Super (MultiSelectFormField, self). _ init _ (* args, ** kwargs)
Def clean (self, value ):
If not value and self. required:
Raise forms. ValidationError (self. error_messages ['required'])
# If value and self. max_choices and len (value)> self. max_choices:
# Raise forms. ValidationError ('you must select a maximum of % s choice % s .'
# % (Apnumber (self. max_choices), pluralize (self. max_choices )))
Return value
Class MultiSelectField (models. Field ):
_ Metaclass _ = models. SubfieldBase
Def get_internal_type (self ):
Return "CharField"
Def get_choices_default (self ):
Return self. get_choices (include_blank = False)
Def _ get_FIELD_display (self, field ):
Value = getattr (self, field. attname)
Choicedict = dict (field. choices)
Def formfield (self, ** kwargs ):
# Don't call super, as that overrides default widget if it has choices
ULTS = {'required': not self. blank, 'label': capfirst (self. verbose_name ),
'Help _ text': self. help_text, 'choices': self. choices}
If self. has_default ():
Defaults ['initial'] = self. get_default ()
Defaults. update (kwargs)
Return MultiSelectFormField (** defaults)
Def get_prep_value (self, value ):
Return value
Def get_db_prep_value (self, value, connection = None, prepared = False ):
If isinstance (value, basestring ):
Return value
Elif isinstance (value, list ):
Return ",". join (value)
Def to_python (self, value ):
If value is not None:
Return value if isinstance (value, list) else value. split (',')
Return''
Def contribute_to_class (self, cls, name ):
Super (MultiSelectField, self). contribute_to_class (cls, name)
If self. choices:
Func = lambda self, fieldname = name, choicedict = dict (self. choices ):",". join ([choicedict. get (value, value) for value in getattr (self, fieldname)])
Setattr (cls, 'get _ % s_display '% self. name, func)
Def validate (self, value, model_instance ):
Arr_choices = self. get_choices_selected (self. get_choices_default ())
For opt_select in value:
If (int (opt_select) not in arr_choices): # the int () here is for comparing with integer choices
Raise exceptions. ValidationError (self. error_messages ['invalid _ choice '] % value)
Return
Def get_choices_selected (self, arr_choices = ''):
If not arr_choices:
Return False
List = []
For choice_selected in arr_choices:
List. append (choice_selected [0])
Return list
Def value_to_string (self, obj ):
Value = self. _ get_val_from_obj (obj)
Return self. get_db_prep_value (value)