django model choice option as a multi select box


Assuming that I have such model

    ('R', 'Red'),
    ('B', 'Yellow'),
    ('G', 'White'),
class Car(models.Model):
    name = models.CharField(max_length=20)
    color= models.CharField(max_length=1, choices=COLORS)

It displays as a selectbox in the admin panel however I would like my admin-user to multi select those colors like many-to-many relationship, how can this be achieved without a ('RB', 'Red&Blue'), type of logic

11/14/2015 5:07:30 AM

Accepted Answer

Can a Car have multiple colors? In that case color ought to be a many to many relationship rather than a CharField. If on the other hand you want to do something like Unix permissions (i.e. Red + Blue, Red + Blue + Green etc.) then assign numeric values of to each of them and make color an integer field.


(After reading comment) You can use a custom form to edit your model in Admin instead of the default ModelForm. This custom form can use a multiple choice widget that lets users select multiple colors. You can then override the clean() method of the form to return a suitably concatenated value ('RB' etc.).

Update 2

Here is some code:

First, remove the choices from the model field. Also increase its maximum size to 2. We don't want choices here - if we do, then we'll have to add a choice for each combination of colors.

class Car(models.Model):
    color= models.CharField(max_length=2)

Second add a custom ModelForm to use in admin app. This form will override color and instead declare it as a multiple choice field. We do need choices here.

    ('R', 'Red'),
    ('B', 'Yellow'),
    ('G', 'White'),

class CarAdminForm(ModelForm):
    color = forms.MultipleChoiceField(choices = COLORS)

    class Meta:
        model = Car

    def clean_color(self):
        color = self.cleaned_data['color']
        if not color:
            raise forms.ValidationError("...")

        if len(color) > 2:
            raise forms.ValidationError("...")

        color = ''.join(color)
        return color

Note that I have added only a couple of validations. You may want more and/or customize the validations.

Finally, register this form with admin. Inside your

class CarAdmin(admin.ModelAdmin):
    form = CarAdminForm, CarAdmin)
8/27/2010 9:22:58 AM

I've constructed a complete working example with meaningful models. It works perfect. I've tested it on Python 3.4.x and Django 1.8.4. At first I run admin panel and create records for each option in Thema model

from django.db import models

class Author(models.Model):
    fname = models.CharField(max_length=50)
    lname = models.CharField(max_length=80)

    def __str__(self):
        return "{0} {1}".format(self.fname, self.lname)

class Thema(models.Model):
        ('tech', 'Technical'),
        ('novel', 'Novel'),
        ('physco', 'Phsycological'),
    name = models.CharField(max_length=20,choices=THEME_CHOICES, unique=True)

    def __str__(self):

class Book(models.Model):

    name = models.CharField(max_length=50)
    author = models.ForeignKey(Author)
    themes = models.ManyToManyField(Thema)

    def __str__(self):
        return "{0} by {1}".format(,

from django import forms

from .models import *

class BookForm(forms.ModelForm):
    themes = forms.ModelMultipleChoiceField(queryset=Thema.objects, widget=forms.CheckboxSelectMultiple(), required=False)

from django.contrib import admin

from .models import *
from .forms import *

class AuthorAdmin(admin.ModelAdmin):

class BookAdmin(admin.ModelAdmin):
    form = BookForm

class ThemaAdmin(admin.ModelAdmin):

Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow