简体   繁体   中英

Return a Http Response In get_queryset

Im using get_queryset, in ListAPIView

I want to check the user's access token, before providing the list, I done the below but the issue is that get_query set does not return a Response, is there a way to return a response, or I should use an alternative :

this my class in the views.py :

class ListProductsOfCategory(generics.ListAPIView):
    serializer_class = ProductSerializer
    lookup_url_kwarg = 'category_id'

    def get_queryset(self):
        # I get the token here from the headers 
        token = self.request.META.get("HTTP_TOKEN", "")
        if not token:
            return Response(
                data={
                    "message": "no token!"
                },
                status=status.HTTP_400_BAD_REQUEST
            )
        if not UserAccess.objects.filter(accessToken=token).exists():
            return Response(
                data={
                    "message": "invalid token!"
                },    
                status=status.HTTP_400_BAD_REQUEST
            )
        category_id = self.kwargs.get(self.lookup_url_kwarg)
        return Product.objects.filter(category_id=category_id)

note that everything is working perfect If I removed the token related part.

thanks in advance.

after last update this is the repsonse :

在此处输入图片说明

I'd suggest you to move check token logic into dispatch() method. It's a better place than get_queryset . Or even better to write your own authentication class in order to share it between views.

With some fixes (see updated get_queryset()) it can be:

UPDATE

I think you can go with built-in restframework.exceptions.AuthenticationFailed . If you are not satisfied with default DRF exceptions you can create your own custom exceptions. For example somewhere in exceptions.py :

from rest_framework.exceptions import APIException

class MissingTokenException(APIException):
    status_code = 400
    default_detail = 'Your request does not contain token'
    default_code = 'no_token'

class InvalidTokenException(APIException):
    status_code = 400
    default_detail = 'Your request contain invalid token'
    default_code = 'invalid_token'

Then you can use them in views.py :

from rest_framework import serializers
from .exceptions import MissingTokenException, InvalidTokenException

class ListProductsOfCategory(generics.ListAPIView):
    serializer_class = ProductSerializer
    lookup_url_kwarg = 'category_id'

    def dispatch(self, *args, **kwargs):
        token = self.request.META.get("HTTP_TOKEN", "")
        if not token:
            raise MissingTokenException
        if not UserAccess.objects.filter(accessToken=token).exists():
            raise InvalidTokenException
        return super().dispatch(*args, **kwargs)

    def get_queryset(self):
        qs = super().get_queryset()
        category_id = self.kwargs.get(self.lookup_url_kwarg)
        return qs.filter(category_id=category_id)

I'm not 100% if I'm getting this right, but I believe you can just use the regular authentication mechanisms that DRF provides. In this particular example, I think this section of the DRF docs should show you how to do it the "DRF" way: Setting Authentication Scheme

If you add the TokenAuthentication scheme to your application, you don't need to verify the token in your get_queryset method, but you can just use decorators to restrict access for function-based views or permission_classes for class-based views:

View-based

I guess this is what you'd be most interested in.

class ListProductsOfCategory(generics.ListAPIView):
    serializer_class = ProductSerializer
    lookup_url_kwarg = 'category_id'

    authentication_classes = (TokenAuthentication, ) # Add others if desired
    permission_classes = (IsAuthenticated,)

Route-based

If you only want to restrict access for some of your routes (eg only post or detail views), then you can write your own permission class. For example, see this question here: How to add django rest framework permissions on specific method only ?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM