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)
