#33714: Better admin support for ArrayFields where the base_field has choices
-------------------------------+--------------------------------------
Reporter: Jaap Roes | Owner: nobody
Type: New feature | Status: new
Component: contrib.admin | Version: dev
Severity: Normal | Resolution:
Keywords: | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------+--------------------------------------
Comment (by Jaap Roes):
We have some workarounds in place to make it work in our projects.
Instead of `ArrayField` we use:
{{{
from django import forms
from django.contrib.postgres.fields import ArrayField
class ChoiceArrayField(ArrayField):
def formfield(self, **kwargs):
defaults = {
"form_class": forms.MultipleChoiceField,
"choices": self.base_field.choices,
**kwargs,
}
# Bypass the ArrayField's formfield, because we don't want it to
pass the unexpected
# base_field to our selected form_class.
return super(ArrayField, self).formfield(**defaults)
}}}
For list filters we use:
{{{
class ChoiceArrayFieldListFilter(admin.SimpleListFilter):
field_name = NotImplemented # Set by subclasses
(ChoiceArrayFieldListFilter.for_field)
def __init__(self, request, params, model, model_admin):
field = model._meta.get_field(self.field_name)
self.parameter_name = field.name
self.title = field.verbose_name
self._choices = field.base_field.choices
super().__init__(request, params, model, model_admin)
def lookups(self, request, model_admin):
return self._choices
def queryset(self, request, queryset):
if value := self.value():
queryset = queryset.filter(**{
f'{self.field_name}__contains': [value]
})
return queryset
@classmethod
def for_field(cls, field_name):
return type(f'{field_name.title()}ListFilter',
(ChoiceArrayFieldListFilter,), {
'field_name': field_name
})
}}}
and for list display purposes we define methods on the admin class that
call this little helper function:
{{{
def _get_array_field_display(obj, field_name):
field = obj._meta.get_field(field_name)
choice_lookup = dict(field.base_field.flatchoices)
return "; ".join(str(choice_lookup.get(value)) for value in
getattr(obj, field_name))
}}}
It would be nice if we can get rid of these workarounds and have this
working in Django Admin without any extra code.
--
Ticket URL: <https://code.djangoproject.com/ticket/33714#comment:1>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/01070180d282f951-d6a13305-6638-415e-bf82-883f031c9ab5-000000%40eu-central-1.amazonses.com.