2012-05-08 46 views
41

我遇到了一个问题,我将request.user分配给了一个名为prior_user的变量,然后对用户进行了实质性验证,然后检查了request.user != prior_user。我期望他们不是一样的,prior_user应该包含`AnonymousUser。令我惊讶的是,他们是一样的。django:django.utils.functional.SimpleLazyObject的用途?

示例代码:

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超人类知识的人都可以提供一些清晰度?

回答

97

auth中间件添加user属性到request这是SimpleLazyObject的一个实例。 SimpleLazyObject,本身是LazyObject的子类。 LazyObject是,如通过实际的代码描述:

一种用于另一类包装可用于延迟包裹类的实例化

SimpleLazyObject只将(上LazyObject_wrapped属性)类通过传入方法,在这种情况下,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的一个实例。

+3

谢谢,这对于像我这样的django初学者非常有帮助! – donogood

+4

+1为了解释! – Anoyz