我正在尝试制作中间件,根据子域等改变用户的某些字段......
唯一的问题是request.user总是在中间件中作为AnonymousUser出现,但是在视图中是正确的用户 . 我已经离开了django在设置中使用的默认身份验证和会话中间件 .
这里有一个类似的问题:Django, request.user is always Anonymous User但是没有使用不同的身份验证方法,并且在调用我自己的中间件之前djangos身份验证正在运行 .
有没有办法在使用DRF时获取中间件中的request.user?我将在这里展示一些示例代码:
class SampleMiddleware(object):
def process_view(self, request, view_func, view_args, view_kwargs):
#This will be AnonymousUser. I need it to be the actual user making the request.
print (request.user)
def process_response(self, request, response):
return response
使用process_request:
class SampleMiddleware(object):
def process_request(self, request):
#This will be AnonymousUser. I need it to be the actual user making the request.
print (request.user)
def process_response(self, request, response):
return response
谢谢!
约旦
5 回答
基于Daniel Dubovski上面非常优雅的解决方案,这里是Django 1.11的中间件示例:
嘿伙计我通过从请求中获取DRF令牌并将request.user加载到与该模型关联的用户来解决此问题 .
我有默认的django身份验证和会话中间件,但似乎DRF在中间件解析用户之后使用它的令牌身份验证(所有请求都是CORS请求,这可能就是原因) . 这是我更新的中间件类:
这也可以在process_view或process_request上使用 .
希望这可以在将来帮助某人 .
在大多数情况下,Daniel Dubovski's solution可能是最好的 .
懒惰对象方法的问题是如果你需要依赖副作用 . 就我而言,无论如何,我都需要为每个请求发生一些事情 .
如果我使用像
request.custom_prop
这样的特殊值,则必须针对发生副作用的每个请求对其进行评估 . 我注意到other people are setting request.user,但它对我不起作用,因为一些中间件或身份验证类会覆盖此属性 .如果DRF支持自己的中间件怎么办?我在哪里可以插上它?在我的情况下最简单的方法(我不需要访问
request
对象,只有经过身份验证的用户)似乎是挂钩到身份验证类本身:然后我可以在我的设置中替换这一行:
我不推广这个解决方案,但也许它会帮助别人 .
Pros:
它解决了这个具体问题
没有双重身份验证
易于维护
Cons:
未在 生产环境 中测试过
事情发生在意想不到的地方
副作用......
我知道's not exactly answering the '我们可以从中间件' question, but I think it'访问它是一个更优雅的解决方案VS在中间件VS中做同样的工作VS DRJ在其基础view class中做了什么 . 至少在我需要的地方,添加到这里更有意义 .
基本上,我只是从DRF的代码中覆盖了'perform_authentication()'方法,因为我需要在请求中添加与当前用户相关的更多内容 . 该方法最初调用'request.user' .
在您自己的视图中,而不是将DRF中的APIView设置为父类,只需将该类设置为父类 .
遇到同样的问题,今天遇到了这个问题 .
TL;DR;
跳过下面的代码示例
Explanation
事情是DRF有自己的事物流,正好在django中间请求life-cycle .
因此,如果正常的中间件流程是:
request_middleware(在开始处理请求之前)
view_middleware(在调用视图之前)
template_middleware(渲染前)
response_middleware(在最终回复之前)
DRF代码覆盖默认的django视图代码,并执行their own code .
在上面的链接中,您可以看到它们使用自己的方法包装原始请求,其中一种方法是DRF身份验证 .
回到你的问题,这就是在中间件中使用
request.user
为时过早的原因,因为它只能获得它的值 after view_middleware ** .我使用的解决方案是让我的中间件设置为
LazyObject
. 这有帮助,因为我的代码(实际的DRF ApiVIew)在DRF's authentication已经设置了实际用户时执行 . 这个解决方案和proposed here一起讨论 .如果DRF有更好的方法来扩展其功能,可能会更好,但事实上,这似乎比提供的解决方案更好(性能和可读性都明智) .
Code Example