How to properly return error when overriding .get_queryset()?
Asked Answered
W

2

5

I read on DRF doc that you can filter againt query parameters by overriding .get_queryset(). I am looking for the best practice, on what to return, in case the filters are incorrect and where to return an error message.

The doc I referred to is here And I include the source code below

class PurchaseList(generics.ListAPIView):
    serializer_class = PurchaseSerializer

    def get_queryset(self):
        """
        Optionally restricts the returned purchases to a given user,
        by filtering against a `username` query parameter in the URL.
        """
        queryset = Purchase.objects.all()
        username = self.request.query_params.get('username', None)
        if username is not None:
            queryset = queryset.filter(purchaser__username=username)
        return queryset

Thank you for your help

Wrongful answered 13/2, 2019 at 9:52 Comment(1)
Don't return an error and ignore if the key is not correct. If you are afraid it'll return too much content, use pagination.Malcommalcontent
S
5

You can do this

from rest_framework import status

class PurchaseList(generics.ListAPIView):
    serializer_class = PurchaseSerializer
    def get_queryset(self):
        try:
            """
            Optionally restricts the returned purchases to a given user,
            by filtering against a username query parameter in the URL.
            """
            queryset = Purchase.objects.all()
            username = self.request.query_params.get('username', None)
            if username is not None:
                    queryset = queryset.filter(purchaser__username=username)
            return queryset
        except:
            return None

    def get(self, request):
        try:
           data=view_serializer(self.get_queryset(),many=True).data
           context = {
               "data" : data,
               "message" : "Contents returned successfully",
               "success" : True
               }
           return Response(context, status=status.HTTP_200_OK)
        except Exception as error:
           context = {'error': str(error), 'success': "false", 'message': 'Failed To Get contents.'}
           return Response(context, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
Sedimentology answered 13/2, 2019 at 10:11 Comment(4)
Thanks for the answer. However returning a 400 throw server error.Wrongful
Can you post me the error? or show screenshot of it?Sedimentology
It returns The response content must be rendered before it can be iterated over. After searching this I found an answer to my issue hereWrongful
I have updated the answer. Now it's correct. You can mark it correct so that others can find it helpful. And thanks for pointing out that we can't return Response inside get_queryset()Sedimentology
S
8

If your API is strict and you need to send some message about the bad filters you can raise an error so DRF knows how to handle it (docs) For example:

from rest_framework.exceptions import ValidationError

class PurchaseList(generics.ListAPIView):
    serializer_class = PurchaseSerializer

    def get_queryset(self):
      ...
      if error:
        raise ValidationError(detail='Invalid Params')
Subjective answered 5/8, 2019 at 22:23 Comment(0)
S
5

You can do this

from rest_framework import status

class PurchaseList(generics.ListAPIView):
    serializer_class = PurchaseSerializer
    def get_queryset(self):
        try:
            """
            Optionally restricts the returned purchases to a given user,
            by filtering against a username query parameter in the URL.
            """
            queryset = Purchase.objects.all()
            username = self.request.query_params.get('username', None)
            if username is not None:
                    queryset = queryset.filter(purchaser__username=username)
            return queryset
        except:
            return None

    def get(self, request):
        try:
           data=view_serializer(self.get_queryset(),many=True).data
           context = {
               "data" : data,
               "message" : "Contents returned successfully",
               "success" : True
               }
           return Response(context, status=status.HTTP_200_OK)
        except Exception as error:
           context = {'error': str(error), 'success': "false", 'message': 'Failed To Get contents.'}
           return Response(context, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
Sedimentology answered 13/2, 2019 at 10:11 Comment(4)
Thanks for the answer. However returning a 400 throw server error.Wrongful
Can you post me the error? or show screenshot of it?Sedimentology
It returns The response content must be rendered before it can be iterated over. After searching this I found an answer to my issue hereWrongful
I have updated the answer. Now it's correct. You can mark it correct so that others can find it helpful. And thanks for pointing out that we can't return Response inside get_queryset()Sedimentology

© 2022 - 2024 — McMap. All rights reserved.