django:django.utils.functional.SimpleLazyObject的目的是什么?

我遇到了一个问题,我把request.user分配给了一个名为prior_user的variables,然后对用户进行了基本的validation,然后检查了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 iethey are the same! 

然后,我发现prior_user实际上包含一个django.utils.functional.SimpleLazyObject的实例,所以我认为它是某种懒惰的查找types的东西,即prior_user的价值是不查找,直到实际使用。 看源代码,我无法证实这一点。

任何有Django经验的人都可以告诉我发生了什么,为什么需要这样做?

这让我有点动摇,因为通常的赋值语句不能像我期望的那样工作,Django中的其他内容也是这样吗? 我也没有看到在文档中描述的这一点。

所以任何拥有django超级人类知识的人都可以提供一些清晰度?

auth中间件添加一个user属性来request这个SimpleLazyObject的实例。 SimpleLazyObject本身是LazyObject的子类。 LazyObject就像实际的代码所描述的那样:

另一个类的包装器,可以用来延迟包装类的实例化

SimpleLazyObject只是通过一个传入的方法(在本例中为get_user )来设置该类( _wrapped上的_wrapped属性)。 这是该方法的代码:

 def get_user(request): if not hasattr(request, '_cached_user'): request._cached_user = auth.get_user(request) return request._cached_user 

这本身实际上只是auth.get_user一个包装,它启用了一种caching机制。 那么这里是最终运行的是什么:

 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在用于某些事情之前是不明确的。 这很重要,因为它可以根据当前的身份validation状态进行调整。 如果您在进行身份validation之前访问其上的属性,它将返回一个实例AnonymousUser ,但是如果您进行身份validation并访问它,则会返回一个User的实例。