2012-05-08 13 views
41

私はrequest.userという変数にprior_userという変数を割り当て、次に本質的にユーザーを認証し、request.user != prior_userかどうかをチェックしました。私はそれらが同じでないことを期待し、prior_userには `AnonymousUser 'が含まれているはずです。驚いたことに、彼らは同じだった。django:django.utils.functional.SimpleLazyObjectの目的は?

サンプルコード:私はその後、prior_userが実際に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の経験をお持ちの方は、何が起こっているのか、なぜ必要なのか教えていただけますか?

通常の代入文は期待通りに機能しないため、Django内の他に何がこのように機能するので、少し動揺してしまいます。また、docsに記載されていることもありませんでした。

だから、djangoの超人間の知識を持つ人は、いくらか明確にすることができますか?

答えて

97

authミドルウェアはSimpleLazyObjectのインスタンスであるrequestuser属性を追加します。 SimpleLazyObjectは、それ自身LazyObjectのサブクラスです。

SimpleLazyObjectを包んだクラスのインスタンス化を遅延させるために使用することができる別のクラスのラッパーは、単にそのクラス(LazyObject_wrapped属性)を設定

:実際のコードで説明したようにLazyObjectは、あります渡されたメソッド(この場合、get_user)を介して渡されます。それ自体が本当にキャッシュメカニズムの並べ替えを可能にauth.get_user単なるラッパーであることを

def get_user(request): 
    if not hasattr(request, '_cached_user'): 
     request._cached_user = auth.get_user(request) 
    return request._cached_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

ありがとう、それは私のようなジャンゴ初心者のために非常に役立った! – donogood

+4

+1すばらしい説明! – Anoyz