request.user返回一个SimpleLazyObject,我该如何“唤醒”它?

我有以下的方法:

def _attempt(actor): if actor.__class__ != User: raise TypeError 

从视图中调用:

 self.object.attempt(self.request.user) 

正如你所看到的,_attempt方法期望actor是typesdjango.contrib.auth.models.User ,但是该对象看起来是django.utils.functional.SimpleLazyObjecttypes的。 这是为什么? 更重要的是,如何将LazyObject (显然是一种用户对象的包装)转换成一个User对象?

有关Request.user更多信息,请访问: https : //docs.djangoproject.com/en/dev/ref/request-response/#django.http.HttpRequest.user此文档似乎表明request.user应该是User对象…

======进行后期编辑=====

我现在有以下方法:

 def _attempt(obj, action, actor, msg): actor.is_authenticated() if isinstance(actor, LazyObject): print type(actor) 

我传递一个用户,但是if条件仍然是真的,actor仍然是一个LazyObject 。 这是为什么?

看到我的答案在类似的问题 。

Django懒加载request.user以便它可以是UserAnonymousUser User取决于身份validation状态。 它只是“唤醒”,并返回适当的类,当一个属性被访问。 不幸的是, __class__不计数,因为这是一个原始的类属性。 在某些情况下,您可能需要知道这实际上是SimpleLazyObjecttypes,因此将其代理到UserAnonymousUser将是错误的。

总之,你根本无法做这个比较,因为你有它。 但是,你真的想在这里做什么? 如果你想要检查它是一个User还是AnonymousUser ,那么就有request.user.is_authenticated()

一般来说,你不应该滥用鸭子打字。 一个参数应该总是一个特别的types或者子types( User或者UserSubClass ),即使它不是必须的 。 否则,你最终会遇到困惑和脆弱的代码。

这应该做到这一点:

 # handle django 1.4 pickling bug if hasattr(user, '_wrapped') and hasattr(user, '_setup'): if user._wrapped.__class__ == object: user._setup() user = user._wrapped 

我不得不写这个,所以我可以添加一个用户到会话字典。 (SimpleLazyObjects不可挑选!)

 user= request.user._wrapped if hasattr(request.user,'_wrapped') else request.user 

然后你使用user而不是request.user

这与UsAaR33的答案类似,但单一线程更适合转换对象。

对于任何想为你的代码写一个失败的“小”unit testing的人,你可以生成一个包装好的User并将其填入请求中。

 from django.contrib.auth import get_user_model from django.test import RequestFactory from django.utils.functional import SimpleLazyObject user = get_user_model().objects.create_user( username='jacob', email='jacob@…', password='top_secret', ) factory = RequestFactory() request = factory.get('/') request.user = SimpleLazyObject(lambda: user) 

看到: