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属性を追加します。、それ自体は のサブクラスです。実際のコードで説明されているように、次のとおりです。requestSimpleLazyObjectSimpleLazyObjectLazyObjectLazyObject

ラップされたクラスのインスタンス化を遅らせるために使用できる別のクラスのラッパー

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 に答える