我遇到了一个问题,我将request.user
分配给名为prior_user
的变量,然后基本上对用户进行了身份验证,然后检查是否request.user != prior_user
。我希望它们不一样,prior_user
应该包含`AnonymousUser。令我惊讶的是,他们是一样的。
示例代码:
prior_user = request.user # request object, obtained froma view
authenticate_user(request) # some function that authenticates
print prior_user.username != request.user.username # returns False i.e.they are the same!
然后我发现prior_user实际上包含一个django.utils.functional.SimpleLazyObject的实例,所以我假设它是某种懒惰的查找类型的东西,即在实际使用之前不会查找prior_user的值。看一下源代码,我无法证实这一点。
任何拥有django经验的人都可以告诉我发生了什么以及为什么需要它?
这让我有些动摇,因为通常的赋值语句不能按我预期的方式工作,Django中的其他内容是什么样的?我也没有在docs中看到这一点。
所以对django有超级人类知识的人都可以提供一些清晰度吗?
答案 0 :(得分:102)
auth
中间件向user
添加request
属性,该属性是SimpleLazyObject
的实例。 SimpleLazyObject
,本身是LazyObject
的子类。 LazyObject
是,如实际代码所述:
另一个类的包装器,可用于延迟包装类的实例化
SimpleLazyObject
仅通过传入方法设置该类(_wrapped
上的LazyObject
属性),在本例中为get_user
。这是该方法的代码:
def get_user(request):
if not hasattr(request, '_cached_user'):
request._cached_user = auth.get_user(request)
return request._cached_user
这本身就是auth.get_user
的包装器,它实现了一种缓存机制。所以这是最终实际运行的内容:
def get_user(request):
from django.contrib.auth.models import AnonymousUser
try:
user_id = request.session[SESSION_KEY]
backend_path = request.session[BACKEND_SESSION_KEY]
backend = load_backend(backend_path)
user = backend.get_user(user_id) or AnonymousUser()
except KeyError:
user = AnonymousUser()
return user
所以,这里真正发生的是request.user
是不明确的,直到它实际用于某事。这很重要,因为它允许它根据当前身份验证状态进行调整。如果您在之前访问上的属性进行身份验证,则会返回实例AnonymousUser
,但如果您进行身份验证然后访问它,则会返回User
的实例。