web-dev-qa-db-ja.com

request.userはSimpleLazyObjectを返しますが、どのように「ウェイク」しますか?

次の方法があります。

def _attempt(actor):
    if actor.__class__ != User:
        raise TypeError

ビューから呼び出されます:

self.object.attempt(self.request.user)

ご覧のとおり、_attemptメソッドはアクターがDjango.contrib.auth.models.User型であると想定していますが、オブジェクトはDjango.utils.functional.SimpleLazyObject型であるように見えます。これはなぜですか?さらに重要なことは、LazyObject(明らかにUserオブジェクトの一種のラッパー)をUserオブジェクトに変換するにはどうすればよいですか?

Request.userの詳細については、こちらをご覧ください。 https://docs.djangoproject.com/en/dev/ref/request-response/#Django.http.HttpRequest.user このドキュメントはrequest.userUserオブジェクトであることを示すため...

======編集後=====

私は今、次のメソッドを持っています:

def _attempt(obj, action, actor, msg): 
    actor.is_authenticated() 
    if isinstance(actor, LazyObject): 
        print type(actor) 

私はユーザーを渡していますが、if条件はまだ真であり、アクターはまだLazyObjectです。これはなぜですか?

54
Himerzi

同様の質問に対する私の答え を参照してください。

Django lazyは_request.user_をロードするため、認証状態に応じてUserまたはAnonymousUserのいずれかになります。属性がアクセスされると、「ウェイクアップ」して適切なクラスを返します。残念ながら、___class___はプリミティブなクラス属性であるためカウントされません。これは実際にはSimpleLazyObject型であるため、UserまたはAnonymousUserにプロキシするのは間違っていることを知る必要がある場合があります。

長いことも短いこともありますが、単にこの比較を行うことはできません。しかし、あなたは何ですか本当にここで達成しようとしていますか? UserであるかAnonymousUserであるかを確認しようとしている場合、たとえば、そのためのrequest.user.is_authenticated()があります。

ただし、一般的な規則として、アヒルのタイピングを乱用しないでください。パラメーターは、haveでなくても、常に特定のタイプまたはサブタイプ(UserまたはUserSubClass)でなければなりません。そうしないと、混乱して壊れやすいコードになってしまいます。

35
Chris Pratt

これはそれを行う必要があります:

# handle Django 1.4 pickling bug
if hasattr(user, '_wrapped') and hasattr(user, '_setup'):
    if user._wrapped.__class__ == object:
        user._setup()
    user = user._wrapped

セッション辞書にユーザーを追加できるように、これを作成する必要がありました。 (SimpleLazyObjectsは選べません!)

16
UsAaR33
user= request.user._wrapped if hasattr(request.user,'_wrapped') else request.user

次に、request.userの代わりにuserを使用します。

これはUsAaR33の答えに似ていますが、オブジェクトを変換するには1ライナーの方が適しています。

9
André Staltz

コードの失敗した「小さな」ユニットテストを作成したい場合は、ラップされたUserを生成し、リクエスト内に詰め込むことができます。

from Django.contrib.auth import get_user_model
from Django.test import RequestFactory
from Django.utils.functional import SimpleLazyObject

user = get_user_model().objects.create_user(
    username='jacob',
    email='jacob@…',
    password='top_secret',
)

factory = RequestFactory()
request = factory.get('/')
request.user = SimpleLazyObject(lambda: user)

見る:

1
jamesc