Search code examples
djangodjango-rest-frameworkdjango-serializerdjango-filterdjango-rest-viewsets

How to filter models by currently authenticated user using ModelViewSet in DRF


I'm working on Django project with Django Rest Framework. I have a model called Server and I want to filter the queryset by the currently authenticated user, but only if "by_user=true" is provided in query params. I'm using ModelViewSet to create the API endpoints. I have overrided the get_queryset and it works fine. But when I return is using super().list(request, *args, **kwargs) it returns the queryset without filtering. Only way I found to return the filtered queryset is by using Response(serializer.data). But I want to use the super().list() method. Any help would be appreciated. Thanks in advance.

Here is Server Model:

class Server(Model):
    name = CharField(max_length=100)
    owner = ForeignKey(
        settings.AUTH_USER_MODEL, on_delete=CASCADE, related_name="server_owner"
    )
    category = ForeignKey(Category, on_delete=CASCADE, related_name="server_category")
    description = CharField(max_length=300, blank=True, null=True)
    members = ManyToManyField(
        settings.AUTH_USER_MODEL, related_name="server_members", blank=True
    )

    def __str__(self):
        return self.name

Here's Serializer:

class ServerSerializer(ModelSerializer):
    class Meta:
        model = Server
        fields = "__all__"

And Here's ViewSet:

class ServerViewSet(ModelViewSet):
    queryset = Server.objects.all()
    serializer_class = ServerSerializer
    filter_backends = [DjangoFilterBackend, OrderingFilter]
    filterset_class = ServerFilter

    def list(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())
        by_user = request.query_params.get("by_user", False)
        if by_user:
            queryset = queryset.filter(members=request.user)
        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)
        # return super().list(request, *args, **kwargs)

Solution

  • The super() keyword is used to call methods and attributes from the inherited/parent class, in your case ModelViewset.

    Returning super().list() will call the .list() method defined in the ModelViewset class and not the one you have defined in your ServerViewSet class.

    Remember the .list() method in the ModelViewset class does not filter the data and that is why you have overridden it in your ServerViewset class so that you can have the data filtered. So you only have to return your filtered data or queryset using return Response(serializer.data).

    There is no need to use super().list() in your case.