Home > OS >  How to filter based on another model in Django ModelViewSet?
How to filter based on another model in Django ModelViewSet?

Time:09-22

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.

  • Related