I currently have a SiteViewSet
using ModelViewSet
that can list, retrieve, create, and update sites from the model Site
.
I want to add a filter to the same SiteViewSet
that lists all the site objects where is_active
is True - but this condition is based on the AdminConfiguration
model.
I was not able to find how to implement a filter in ModelViewSet
based on conditions of another model. Is the filtered endpoint /v1/site/?is_active=True
possible to implement in the same SiteViewSet
or should I create a separate view to achieve this via the more flexible APIView
?
SiteViewSet
:
class SiteViewSet(viewsets.ModelViewSet):
model = Site
lookup_field = 'uuid'
pagination_class = PageNumberPagination
serializer_class = SiteSerializer
queryset = Site.objects.all()
Site
Model:
class Site(models.Model):
uuid = models.UUIDField(
default=uuid.uuid4,
unique=True)
domain_name = models.CharField(max_length=255, unique=True)
AdminConfiguration
Model:
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
CodePudding user response:
In DRF filter based on another model is the same that filter against a model field. And you achieve this by override the get_queryset method like this :
we assume that you have declared your OneToOneField like :
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 : Your is_active
field is a property ! So i have never tested with @property
field of a model. But it work fine with standard fields.
Don't also forget to remove the queryset
attribute if you override get_queryset
method. One of them, not both.