【问题标题】:Return a Http Response In get_queryset在 get_queryset 中返回一个 Http 响应
【发布时间】:2018-11-02 07:52:32
【问题描述】:

我在 ListAPIView 中使用 get_queryset

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

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

请注意,如果我删除了与令牌相关的部分,则一切正常。

提前致谢。

上次更新后,这是回复:

【问题讨论】:

  • 用 serializer.ValidationError 更新了我的分析器(默认 http 代码 400)
  • 您应该为此使用身份验证和权限类。这将是更好的方法。

标签: python django django-rest-framework


【解决方案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)

【讨论】:

  • 这似乎工作我只有一个问题,我不想引发验证错误 500 ,我想引发一个自定义错误,你能帮忙吗?
  • @MhmdRizk 我已经用自定义错误示例更新了我的答案。顺便说一句,验证错误返回 400 代码,就像您问题的代码一样。请参阅 drf 异常文档的链接。
  • 我添加了我在尝试您的答案时得到的回复
  • @MhmdRizk 您需要在邮递员请求中添加 Content-Type: application/json 标头。然后你应该得到 json 响应。请参阅stackoverflow.com/questions/31108075/… 以供参考
  • 我试过添加这个,也试过 Content-Type : application/x-www-form-urlencoded,但是没有用
【解决方案2】:

如果我做对了,我不是 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 ?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-02-14
    • 2022-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-27
    • 2020-12-24
    相关资源
    最近更新 更多