为啥“本机”视图和 ModelViewSet 之间的请求对象不一样?
Posted
技术标签:
【中文标题】为啥“本机”视图和 ModelViewSet 之间的请求对象不一样?【英文标题】:Why is request object not the same between a "native" view and a ModelViewSet?为什么“本机”视图和 ModelViewSet 之间的请求对象不一样? 【发布时间】:2018-05-04 10:58:39 【问题描述】:我正在使用 Django Rest Framework (DRF) 构建 API,并通过社交应用启用身份验证/注册。
为了通过他们的社交帐户对用户进行身份验证,我使用了 Django rest-framework Social Oauth2,它的工作原理就像一个魅力。为了确保我的用户已登录,我在我的应用的 views.py 中创建了一个非常简单的视图:
def index(request):
return HttpResponse("is_anonymous: %s" % request.user.is_anonymous)
浏览器中的结果如下(表示用户已登录):
is_anonymous: 假
现在,当我使用 DRF 构建 API 时,我可能需要在我的一个视图集中检索当前用户(来自 request.user)的一些数据,但在以下代码中,结果不是我所期望的:
class HelloViewSet(viewsets.ModelViewSet):
queryset = Hello.objects.all()
serializer_class = HelloSerializer
# This is just a random ViewSet, what is
# important is the custom view below
@action(detail=False)
def test(self, request):
return Response(request.user.is_anonymous)
这里的结果显示用户没有登录:
是的
所以第一个视图显示 request.user.is_anonymous = False,第二个视图显示 request.user.is_anonymous = True。两个视图都在同一个应用程序的同一个文件views.py中。
我在这里想念什么?我们不应该在 API REST 中获取用户实例吗?
【问题讨论】:
【参考方案1】:我想这是因为您的第一个视图是纯 Django 并且没有使用 DRF 的DEFAULT_AUTHENTICATION_CLASSES
。要启用它,您可以添加@api_view
装饰器:
from rest_framework.decorators import api_view
from rest_framework.response import Response
@api_view()
def index(request):
return Response("is_anonymous: %s" % request.user.is_anonymous)
您还应该更新 DEFAULT_AUTHENTICATION_CLASSES
以启用 OAuth,如下所示:
REST_FRAMEWORK =
...
'DEFAULT_AUTHENTICATION_CLASSES': (
...
'oauth2_provider.contrib.rest_framework.OAuth2Authentication',
'rest_framework_social_oauth2.authentication.SocialAuthentication',
),
【讨论】:
正如您所猜测的,两个视图使用的身份验证系统似乎不同,现在两个视图都为“request.user.is_anonymous”发送 True。但这仍然意味着如果视图在“纯 django 视图”之外,我无法访问登录用户的数据,因为他被认为是匿名的(注意:我使用 facebook 登录)。有没有办法让登录操作使用上面给出的默认身份验证类? (我不知道这是否是问题所在,我只是觉得我的登录没有使用正确的身份验证类) @SugarMouse 您是否提供了Authorization: Bearer <token>
标头?
我没有,是强制性的吗?我应该如何获得这个令牌?上次我使用 /auth/token 路由检索用户的令牌,但我必须添加用户名和密码数据作为参数,但“社交用户”没有密码
@SugarMouse 没有此令牌 DRF 无法验证用户。您需要将社交令牌转换为访问令牌。检查 django rest social auth 文档以阐明如何做。
我尝试使用 OAuth 2.0 却不知道它是如何工作的,显然迟早我缺乏理解会成为一个问题。授权中传递的这个令牌确实是我要找的!【参考方案2】:
As neverwalkaloner mentioned in the in the comments,问题是我没有通过Authorization: Bearer <token>
在标头中传递任何access_token,因此服务器当然无法识别发出请求的“已登录”用户。使用 curl(或 Postman),我可以添加此令牌以进行检查,并且它起作用了。
【讨论】:
以上是关于为啥“本机”视图和 ModelViewSet 之间的请求对象不一样?的主要内容,如果未能解决你的问题,请参考以下文章
Django Rest Framework ModelViewSet 视图没有从数据表中看到 CSRFToken
将 django-rest-framework 中的超链接添加到 ModelViewSet