在get_queryset中返回Http响应

时间:2018-11-02 07:52:32

标签: python django django-rest-framework

我在ListAPIView中使用get_queryset

我想在提供列表之前检查用户的访问令牌,我做了下面的工作,但问题是get_query设置未返回Response,有没有办法返回响应,或者我应该使用替代方法:

这是我在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)

请注意,如果我删除了与令牌相关的部分,那么一切都会正常进行。

先谢谢。

最后一次更新后,这是响应:

enter image description here

2 个答案:

答案 0 :(得分:1)

我建议您将检查令牌逻辑移至dispatch()方法中。比get_queryset更好。甚至最好编写自己的身份验证类,以便在视图之间共享它。

通过一些修复(请参阅更新的get_queryset()),它可以是:

更新

我认为您可以使用内置的restframework.exceptions.AuthenticationFailed。 如果您对default DRF exceptions不满意,则可以创建自己的自定义例外。例如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'

然后您可以在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)

答案 1 :(得分:0)

如果我做对了,我不是100%,但是我相信您可以使用DRF提供的常规身份验证机制。在这个特定示例中,我认为DRF文档的这一部分应向您展示如何以“ DRF”方式进行操作:Setting Authentication Scheme

如果将TokenAuthentication方案添加到应用程序中,则无需在get_queryset方法中验证令牌,但是您可以使用修饰符来限制对基于函数的视图的访问,或者permission_classes用于基于类的视图:

基于视图的

我想这是您最感兴趣的。

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

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

基于路由

如果您只想限制某些路线的访问权限(例如,仅发布或查看详细信息),则可以编写自己的权限类。例如,在这里看到这个问题:How to add django rest framework permissions on specific method only ?