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')