Skip to content

Instantly share code, notes, and snippets.

@danni
Created March 8, 2016 08:52
Show Gist options
  • Select an option

  • Save danni/f55c4ce19598b2b345ef to your computer and use it in GitHub Desktop.

Select an option

Save danni/f55c4ce19598b2b345ef to your computer and use it in GitHub Desktop.
Multi Choice Django Array Field
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 1.9's postgres ArrayField
and a MultipleChoiceField for its formfield.
Usage:
choices = ChoiceArrayField(models.CharField(max_length=...,
choices=(...,)),
default=[...])
"""
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)
@anyidea

anyidea commented Aug 10, 2023 •

Copy link
Copy Markdown

After combining all the previous answers, below works for me, Django 4.2, Python 3.11

from django import forms
from django.contrib.postgres.fields import ArrayField


class _TypedMultipleChoiceField(forms.TypedMultipleChoiceField):
    def __init__(self, *args, **kwargs):
        kwargs.pop("base_field", None)
        kwargs.pop("max_length", None)
        super().__init__(*args, **kwargs)


class ChoiceArrayField(ArrayField):
    """
    A field that allows us to store an array of choices.

    Uses Django 4.2's postgres ArrayField
    and a TypeMultipleChoiceField for its formfield.

    Usage:

        choices = ChoiceArrayField(
            models.CharField(max_length=..., choices=(...,)), blank=[...], default=[...]
        )
    """
    def formfield(self, **kwargs):
        defaults = {
            'form_class': _TypedMultipleChoiceField,
            'choices': self.base_field.choices,
            'coerce': self.base_field.to_python,
        }
        defaults.update(kwargs)
        # Skip our parent's formfield implementation completely as we don't care for it.
        # pylint:disable=bad-super-call
        return super().formfield(**defaults)

@andreasnuesslein

Copy link
Copy Markdown

Thanks everybody. using @anyidea 's solution. works nicely

@sam-ghosh

Copy link
Copy Markdown

Thanks this solution works very well

@arnaud-penet

Copy link
Copy Markdown

Thanks you 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment