My name is Piotr, a passionate pythonista and this is my blog!
Django multi-select choice field in admin panel
Posted at — Jan 24, 2022
Let the first cast a stone who did not use Django only because it has already a built-in admin panel…
(of course, Django is having a lot of useful features and possibilities apart from admin).
Recently I found myself in a situation where I needed to allow admin users to set up a list of labels or tags
on a table with a limited set of values. This value is “read-only” on the API side and “write-only” on the admin side.
In this short post, I would like to present a couple of different ways how to set up such a multiple value field.
The first option will be to use an array of char fields with or without an additional widget and the second one will use a JSON field and
represent it nicely in the admin panel.
Using a Django lib ArrayField with CharField without any modifications will result in a simple text field allowing to add of comma-separated choice values.
In this case, the solution will work on the API side returned as a list of strings but it will not be super UX oriented because the user does not know about possible choices.
By modifying an ArrayField we can get a better display of the selected fields and all possible choice values.
Each of them is selectable with CMD/ctr button.
Modified Django ArrayField with a CheckboxSelectMultiple widget
from django import forms
from django.contrib.postgres.fields import ArrayField
from django.db import models
classModifiedArrayField(ArrayField):
defformfield(self, **kwargs):
defaults = {
"form_class": forms.MultipleChoiceField,
"choices": self.base_field.choices,
"widget": forms.CheckboxSelectMultiple,
**kwargs
returnsuper(ArrayField, self).formfield(**defaults)
Introducing a widget might make it more readable and visible in terms of the selection.
JSON field (by django-jsonform) with array of strings
I found this package very (
django-jsonform
) interesting and useful due to its support to the JSON field.
It is also having support to ArrayField which is similar to previous examples but includes a better visual display.
I would like to present a JSON field for an array of strings and also a little bit more advanced schema including a list of dictionaries.
The most important definition apart from the field is a schema. JSON schema of input data will define how the UI will generate.
Visual overview and dropdown with choice fields are way better.
Additionally, JSON (JSONB field from PostgreSQL) if a way more flexible way of keeping those values
JSON field (by django-jsonform) with an array of dicts
The problem with a list of strings starts when we need to support more complex objects.
In my case, a label should have multiple fields like the color (string), value (int), and groups (list of strings).
I didn’t want to introduce a new table because of many reasons, mostly
because of joins (table already had a lot of them) and the “labels” field is read-only without any filtering.