Better ArrayField admin widget?
I take no credit for this (original source), but if you are using PostgreSQL as the database and are happy to use the Postgres-specific ArrayField implementation there is an even easier option: subclass ArrayField
on the model and override the default admin widget. A basic implementation follows (tested in Django 1.9, 1.10, 1.11, 2.0, 2.1 & 2.2):
models.py
from django import forms
from django.db import models
from django.contrib.postgres.fields import ArrayField
class ChoiceArrayField(ArrayField):
"""
A field that allows us to store an array of choices.
Uses Django's Postgres ArrayField
and a MultipleChoiceField for its formfield.
"""
def formfield(self, **kwargs):
defaults = {
'form_class': forms.MultipleChoiceField,
'choices': self.base_field.choices,
}
defaults.update(kwargs)
# Skip our parent's formfield implementation completely as we don't
# care for it.
# pylint:disable=bad-super-call
return super(ArrayField, self).formfield(**defaults)
FUNCTION_CHOICES = (
('0', 'Planning'),
('1', 'Operation'),
('2', 'Reporting'),
)
class FunctionModel(models.Model):
name = models.CharField(max_length=128, unique=True)
function = ChoiceArrayField(
base_field=models.CharField(max_length=256, choices=FUNCTION_CHOICES),
default=list)
This is a better version of an already accepted solution. Using "CheckboxSelectMultiple" makes it more usable in the admin page.
class ChoiceArrayField(ArrayField):
def formfield(self, **kwargs):
defaults = {
'form_class': forms.TypedMultipleChoiceField,
'choices': self.base_field.choices,
'coerce': self.base_field.to_python,
'widget': forms.CheckboxSelectMultiple,
}
defaults.update(kwargs)
return super(ArrayField, self).formfield(**defaults)
For OP, or anyone out there looking, between these helpful bits you should be good to go:
- 1. Extending
SelectMultiple
orCheckboxSelectMultiple
widget to parsearrayfield
and - 2. Creating or extending admin form to display the
arrayfield
using the widget above