from django.forms import MultipleChoiceField
from django.forms.widgets import CheckboxSelectMultiple
# Widget
class CSICheckboxSelectMultiple(CheckboxSelectMultiple):
def value_from_datadict(self, data, files, name):
# Return a string of comma separated integers since the database, and
# field expect a string (not a list).
return ','.join(data.getlist(name))
def render(self, name, value, attrs=None, choices=()):
# Convert comma separated integer string to a list, since the checkbox
# rendering code expects a list (not a string)
if value:
value = value.split(',')
return super(CSICheckboxSelectMultiple, self).render(
name, value, attrs=attrs, choices=choices
)
# Form field
class CSIMultipleChoiceField(MultipleChoiceField):
widget = CSICheckboxSelectMultiple
# Value is stored and retrieved as a string of comma separated
# integers. We don't want to do processing to convert the value to
# a list like the normal MultipleChoiceField does.
def to_python(self, value):
return value
def validate(self, value):
# If we have a value, then we know it is a string of comma separated
# integers. To use the MultipleChoiceField validator, we first have
# to convert the value to a list.
if value:
value = value.split(',')
super(CSIMultipleChoiceField, self).validate(value)
##########
# Example
##########
# models.py
from django.db import models
CHOICE0 = 0
CHOICE1 = 1
CHOICE2 = 2
CHOICE3 = 3
MY_CHOICES = (
(CHOICE0, 'Choice 0'),
(CHOICE1, 'Choice 1'),
(CHOICE2, 'Choice 2'),
(CHOICE3, 'Choice 3'),
)
class MyModel(models.Model):
my_csi_field = models.CommaSeparatedIntegerField(
'comma separated ints', max_length=255, blank=True,
default='',
choices=MY_CHOICES
)
# admin.py
from django.contrib import admin
from django import forms
class MyModelForm(forms.ModelForm):
my_csi_field = CSIMultipleChoiceField(
required=False,
)
class Meta:
model = MyModel
class MyModelAdmin(admin.ModelAdmin):
form = MyModelForm
admin.site.register(MyModel, MyModelAdmin)
Comments