54

我遇到了一个问题,我分配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 中还有什么这样的行为?我也没有在文档中看到这一点。

所以任何对 django 有超人了解的人都可以提供一些清晰的信息吗?

4

1 回答 1

117

auth中间件添加了一个user属性,requestSimpleLazyObject. SimpleLazyObject, 本身是 的子类LazyObjectLazyObject是,如实际代码所述:

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

SimpleLazyObject仅通过传入的方法设置该类(_wrapped属性 on ),在本例中为. 这是该方法的代码:LazyObjectget_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

于 2012-05-08T22:01:31.020 回答