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

Him*_*rzi 56 python django django-contrib django-users

我有以下方法:

def _attempt(actor):
    if actor.__class__ != User:
        raise TypeError
Run Code Online (Sandbox Code Playgroud)

从视图中调用:

self.object.attempt(self.request.user)
Run Code Online (Sandbox Code Playgroud)

如您所见,_attempt方法期望actor是类型django.contrib.auth.models.User,但是对象看起来是类型django.utils.functional.SimpleLazyObject.为什么会这样?更重要的是,如何将LazyObject(显然是一种User对象的包装器)转换为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) 
Run Code Online (Sandbox Code Playgroud)

我正在传递一个用户,但if条件仍然是真的,演员仍然是LazyObject.为什么会这样?

Chr*_*att 37

在类似的问题上看到我的答案.

Django延迟加载,request.user以便它可以是User或者AnonymousUser取决于身份验证状态.它只会"唤醒"并在访问属性时返回相应的类.不幸的是,__class__不计算因为这是一个原始的类属性.在某些情况下,您可能需要知道这实际上是一种SimpleLazyObject类型,因此将其代理到User或将是错误的AnonymousUser.

无论长短,你根本无法进行这种比较.但是,你真的想在这里实现什么?如果你想检查它是否是一个User或者AnonymousUser,有request.user.is_authenticated()针对,例如.

但作为一般规则,你不应该滥用鸭子打字.参数应该始终是特殊类型或子类型(UserUserSubClass),即使它不是必须的.否则,您最终会遇到令人困惑和脆弱的代码.

  • 谢谢你的回答克里斯.实际上,我正在尝试检查它是用户还是匿名用户.我现在有以下方法:`def _attempt(obj,action,actor,msg):actor.is_authenticated()if isinstance(actor,LazyObject):print type(actor)`我正在传递一个用户,但是如果condition仍然为true,则actor仍然是LazyObject.为什么会这样? (2认同)
  • 我们一直用简单的术语来讲,但实际上,request.user总是*一个`SimpleLazyObject`.实例化的用户(无论是`User`还是`AnonymousUser`)作为属性存储在其上,它只是将对自身的大多数属性的请求代理到用户对象上的属性(`__class__`是一个值得注意的例外). (2认同)

UsA*_*R33 16

这应该这样做:

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

我必须写这个,所以我可以添加用户到会话字典.(SimpleLazyObjects不可选!)


And*_*ltz 9

user= request.user._wrapped if hasattr(request.user,'_wrapped') else request.user
Run Code Online (Sandbox Code Playgroud)

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

这与UsAaR33的答案类似,但是单行程转换对象更好.

  • 它是类似的,但是如果`_wrapped`部分未正确初始化,它不会尝试在用户对象上调用`_setup()`.我认为出于这个原因,UsAaR33的答案更可取. (4认同)