Как фильтровать на основе другой модели в Django ModelViewSet?
В настоящее время у меня есть SiteViewSet
, использующий ModelViewSet
, который может перечислять, извлекать, создавать и обновлять сайты из модели Site
.
Я хочу добавить фильтр к тому же SiteViewSet
, который перечисляет все объекты сайта, где is_active
равно True - но это условие основано на AdminConfiguration
модели.
Я не смог найти, как реализовать фильтр в ModelViewSet
на основе условий другой модели. Можно ли реализовать фильтрованную конечную точку /v1/site/?is_active=True
в той же SiteViewSet
или мне следует создать отдельное представление для достижения этого с помощью более гибкого APIView
?
SiteViewSet
:
class SiteViewSet(viewsets.ModelViewSet):
model = Site
lookup_field = 'uuid'
pagination_class = PageNumberPagination
serializer_class = SiteSerializer
queryset = Site.objects.all()
Site
Модель:
class Site(models.Model):
uuid = models.UUIDField(
default=uuid.uuid4,
unique=True)
domain_name = models.CharField(max_length=255, unique=True)
AdminConfiguration
Модель:
class AdminConfiguration(models.Model):
site = models.OneToOneField(
Site,
on_delete=models.CASCADE)
always_active = models.BooleanField(default=False)
subscription_ends = models.DateTimeField(
default=set_default_expiration)
@property
def is_active(self):
active_status = self.always_active or self.subscription_ends > timezone.now()
return active_status
В DRF фильтр на основе другой модели - это то же самое, что фильтр по полю модели. И вы достигаете этого, переопределяя метод get_queryset следующим образом :
мы предполагаем, что вы объявили свое поле OneToOneField как :
site = models.OneToOneField(Site, on_delete=models.CASCADE, related_name='admin_config')
.
def get_queryset(self):
queryset = Site.objects.filter(admin_config__is_active=True)
.filter(related_model_name__field=value)
NB : Ваше is_active
поле является свойством! Поэтому я никогда не тестировал с @property
полем модели. Но оно прекрасно работает со стандартными полями.
Не забудьте также удалить атрибут queryset
, если вы переопределяете метод get_queryset
. Один из них, а не оба.