我遇到了一个问题,我分配request.user了一个名为的变量prior_user,然后从本质上对用户进行了身份验证,然后检查了是否request.user != prior_user。我希望它们不一样,prior_user应该包含 AnonymousUser。令我惊讶的是,它们是相同的。
request.user
prior_user
request.user != prior_user
样例代码:
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中还有什么其他行为呢?我也没有在文档中看到这一点。
因此,具有django超级人类知识的人可以提供一些清晰度吗?
该auth中间件添加user到属性request就是实例SimpleLazyObject。SimpleLazyObject本身是的子类LazyObject。LazyObject如实际代码所述:
auth
user
request
SimpleLazyObject
LazyObject
另一个类的包装器,可用于延迟所包装类的实例化
SimpleLazyObject只是通过传入的方法(在这种情况下为)设置该类(的_wrapped属性on 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,它启用了一种缓存机制。因此,这实际上是最终运行的:
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。
AnonymousUser
User