2012-05-08 48 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