Django-filter: Как получить варианты из связанной модели?

Я пытаюсь создать фильтр и получить варианты из связанной модели. Возможно ли это?

Мои модели:

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)

Мой набор представлений:

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

После прочтения документации кажется, что ModelChoiceFilter используется, если вы хотите фильтровать из выбора другой модели. Так что в вашем случае вы бы использовали обычные ChoiceFilter

from .models import Period

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

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

В документации, однако, они определяют выбор следующим образом:

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

И нет,

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

Так что если это не работает, возможно, вам придется заменить PeriodType на:

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

Используйте поле ChoiceFilter вместо ModelChoiceFilter

class PeriodFilter(django_filters.rest_framework.FilterSet):
  type = django_filters.ChoiceFilter(choices=Period.PeriodType.choices, field_name='period__type', label='Type')
Вернуться на верх