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.
