我在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)
请注意,如果我删除了与令牌相关的部分,那么一切都会正常进行。
先谢谢。
最后一次更新后,这是响应:
答案 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 ?