はい、可能ですが、それほど簡単ではありません。複雑な要因は、Djangoのlogin_required
デコレータが実際には2レベルの間接(1つの動的関数と1つの他のデコレータ)を通過し、__call__
メソッドを持つクラスであるdjango.contrib.auth.decorators.CheckLoginになります。
のは、あなたがこのようになります非ジャンゴ、ありふれ装飾された機能を持っているとしましょう:foo
は、ラップされた関数は、関数オブジェクトの名前をチェックするような単純なことができているかどうかの確認
def my_decorator(func):
def inner():
return func()
return inner
@my_decorator
def foo():
print foo.func_name
# results in: inner
。関数内でこれを行うことができます。名前は実際には最後のラッパー関数の名前になります。より複雑な場合は、特に何かを探している場合は、inspect
モジュールを使用して現在のフレームから外側のフレームを上に移動することができます。ジャンゴの場合
が、しかし、デコレータは、実際に_CheckLogin
クラスのインスタンスであるという事実は、関数が本当に関数ではないので、何のfunc_name
性質を持っていないことを意味します。上記のコードをしようとすると例外が発生します。
しかし、django.contrib.auth.decorators._CheckLogin
のソースコードを見ると、_CheckLogin
インスタンスにはlogin_url
というプロパティがあることがわかります。これは、テストするための非常に簡単なことです。また、他の認証デコレータを実装するために使用される
@login_required
def my_view(request):
is_private = hasattr(my_view, 'login_url')
_CheckLogin
ので、このアプローチはまた、permission_required
のために働くだろう、など私は実際にこれを使用する必要があったことがありませんしかし、1つのビューの周りに複数のデコレータがある場合は、私が実際に探しているものについてコメントすることはできません。読者に残された課題は、フレームスタックを調べることでしょう。
しかし、私は未審査の編集上のアドバイスとして、このようにラップされているかどうかを確認するために関数自体をチェックしてみてください。おそらく、新しい開発者が他のデコレータで叩かれてプロジェクトに来たときに、予想外の動作が起こるのを待っていると思います。実際、djangoフレームワーク自体の変化にも晒されています...セキュリティリスクが発生するのを待っています。
私はVan Galeのアプローチを明示的なものとして推奨しています。そのため、はるかに堅牢な実装です。
あなたの最初のコードブロックは書かれたとおりに動作しません。 my_decoratorは渡された関数を全滅させるので、print文をfooに入れるのは役に立たない。 –
Davidさん、ありがとうございました...私が入力したものを慎重に読まなくても、最初のブロックをめくってメインポイントに到達しました。編集を気に入ってください。 –
詳細な回答ありがとうございます。あなたのエンディングのコメントは、私がやっていることです。私の場合は、 "正しい"方法はあまりにも複雑で堅牢ではないと思います。 –