Home > OS >  django-filter: How to get the choices from related model?
django-filter: How to get the choices from related model?

Time:11-05

Im trying to create a filter, and get the choices from the related model. Is it possible?

My models:

class Container(models.Model):
  description = models.CharField(max_length=255)

class Period(models.Model):

  class PeriodType(models.TextChoices):
    LONG = 'long', 'Long period'
    SHORT = 'short', 'Short period'

  container = models.ForeignKey(to=Container, null=True, blank=True, on_delete=models.SET_NULL)
  type = models.CharField(max_length=15, choices=PeriodType.choices, null=True, blank=True)

My viewset:

class ContainerFilter(django_filters.FilterSet):
  type_of_period = django_filters.ModelChoiceFilter(Period.objects.all(), field_name='period__type', label='Type')

  class Meta:
    model = models.Container
    fields = ['type_of_period',]

class ContainerModelViewSet(viewsets.ModelViewSet):
  queryset = models.Container.objects.all()
  lookup_field = 'id'
  filter_backends = [filters.SearchFilter, django_filters.rest_framework.DjangoFilterBackend]
  search_fields = ['description',]
  filter_class = ContainerFilter

CodePudding user response:

Use ChoiceFilter field instead of ModelChoiceFilter

class PeriodFilter(django_filters.rest_framework.FilterSet):
  type = django_filters.ChoiceFilter(choices=Period.PeriodType.choices, field_name='period__type', label='Type')

CodePudding user response:

After reading the docs it seems ModelChoiceFilter is used if you want to filter from a choice of another model. So in your case you would use regular ChoiceFilter

from .models import Period

class ContainerFilter(FilterSet):
    type_of_period = ChoiceFilter(choices=Period.PeriodType)

    class Meta:
        model = models.Container
        fields = ['type_of_period',]

In the docs however, they are defining the choices like so:

STATUS_CHOICES = (
    (0, 'Regular'),
    (1, 'Manager'),
    (2, 'Admin'),
)

And not,

class PeriodType(models.TextChoices):
    LONG = 'long', 'Long period'
    SHORT = 'short', 'Short period'

So if it doesn't work maybe you have to replace PeriodType with:

PERIOD_CHOICES = (
    ('long', 'Long period'),
    ('short', 'Short period'),
)
  • Related