Recommend ArrayField for PostgreSQL users
Closed this issue · 2 comments
In the interest of the community, I would propose to add a recommendation to the README for PostgreSQL users to use the native django.contrib.postgres.fields.ArrayField instead of this module.
In my opinion this is advantageous from several perspectives:
- It removes the need for an additional dependency
- It is well documented in the official Django documentation
- It enables to use different data types as child field (e.g. CharField(), IntegerField(), etc.)
- It provides handy contains queries (no need to use __regex)
- Works with DRF out of the box (no need to excplicitly declare MultipleChoiceField on the serializer)
If there are resons not to agree with the above, I would propose to make it clear in the README what advantages this package brings over Django's native ArrayField.
One further note, to get the Django Admin to display a multi-select form field in the UI, a custom field can be used to extend the ArrayField:
from django import forms
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 the parent's formfield implementation completely as it does not matter.
return super(ArrayField, self).formfield(**defaults) # pylint:disable=bad-super-call
@LukasKlement This is a fantastic solution when using Postgres, thanks! I'd been trying to use an array field without an extra dependency all day and didn't realize it could be this simple - and this clean. (I'm not particularly experienced with Django.)
Note for anyone wanting to use a different widget than the default multi-select list that forms.MultipleChoiceField
uses, you can specify a default widget, too, for instance a checkbox multiselect:
...
class ChoiceArrayField(ArrayField):
...
def formfield(self, **kwargs):
defaults = {
'form_class': forms.MultipleChoiceField,
'choices': self.base_field.choices,
'widget': forms.CheckboxSelectMultiple,
}
...
Correct. This project is a bit of a workaround for non-PostgreSQL users, and ArrayFields would probably be a cleaner solution for PostgreSQL users.