次の方法があります。
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.user
がUser
オブジェクトであることを示すため...
======編集後=====
私は今、次のメソッドを持っています:
def _attempt(obj, action, actor, msg):
actor.is_authenticated()
if isinstance(actor, LazyObject):
print type(actor)
私はユーザーを渡していますが、if
条件はまだ真であり、アクターはまだLazyObject
です。これはなぜですか?
同様の質問に対する私の答え を参照してください。
Django lazyは_request.user
_をロードするため、認証状態に応じてUser
またはAnonymousUser
のいずれかになります。属性がアクセスされると、「ウェイクアップ」して適切なクラスを返します。残念ながら、___class__
_はプリミティブなクラス属性であるためカウントされません。これは実際にはSimpleLazyObject
型であるため、User
またはAnonymousUser
にプロキシするのは間違っていることを知る必要がある場合があります。
長いことも短いこともありますが、単にこの比較を行うことはできません。しかし、あなたは何ですか本当にここで達成しようとしていますか? User
であるかAnonymousUser
であるかを確認しようとしている場合、たとえば、そのためのrequest.user.is_authenticated()
があります。
ただし、一般的な規則として、アヒルのタイピングを乱用しないでください。パラメーターは、haveでなくても、常に特定のタイプまたはサブタイプ(User
またはUserSubClass
)でなければなりません。そうしないと、混乱して壊れやすいコードになってしまいます。
これはそれを行う必要があります:
# 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は選べません!)
user= request.user._wrapped if hasattr(request.user,'_wrapped') else request.user
次に、request.user
の代わりにuser
を使用します。
これはUsAaR33の答えに似ていますが、オブジェクトを変換するには1ライナーの方が適しています。
コードの失敗した「小さな」ユニットテストを作成したい場合は、ラップされた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)
見る: