我有以下方法:
def _attempt(actor):
if actor.__class__ != User:
raise TypeError
这是从视图叫:
self.object.attempt(self.request.user)
正如你所看到的,_attempt方法希望演员是类型django.contrib.auth.models.User
,但对象似乎是类型django.utils.functional.SimpleLazyObject
。 为什么会这样? 更重要的是,我怎么能转换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
条件仍然为真,演员仍是一个LazyObject
。 为什么会这样?
请参见上一个类似的问题我的答案 。
Django的延迟加载request.user
,以便它可以是User
或AnonymousUser
根据认证状态。 它只是被“唤醒”,当一个属性上它访问返回相应的类。 不幸的是, __class__
不计,因为这是一个原始的类属性。 有场合,你可能需要知道,这其实是一个SimpleLazyObject
类型,因此这将是错误的代理它给User
或AnonymousUser
。
长与短,你根本无法为你拥有了它这样做比较。 但是,什么是你真正想在这里实现? 如果你想检查它是否是一个User
或AnonymousUser
,还有的request.user.is_authenticated()
的,例如。
虽然作为一般规则,你不应该滥用鸭打字。 一个参数应始终是一个特别类型或子类型( 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不picklable!)
user= request.user._wrapped if hasattr(request.user,'_wrapped') else request.user
然后使用user
,而不是request.user
。
这类似于UsAaR33的答案,而是一个班轮是用于转换对象更好。
对于任何人想要写你的代码,一个失败的“小”单元测试,您可以生成一个包裹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)
看到:
https://github.com/django/django/blob/master/tests/utils_tests/test_lazyobject.py有关懒惰对象电流测试。
https://docs.djangoproject.com/en/dev/topics/testing/advanced/#django.test.RequestFactory的最新信息RequestFactory
。