2017-01-27 8 views
2

私は、それらが保護する必要がある権限チェックとビューの階層を持っています。たとえば、これらの2つのチェックを考えてみましょう。クラスベースのビューに適用されるデコレータの作成

def has_profile(user): 
    return user.profile is not None 

def is_a_sorcerer(user): 
    return user.profile.category == 'sorcerer' 

ユーザーがプロファイルを持っている場合はis_a_sorcererに電話するのが理にかなっています。

一部のビューは、プロファイルを持つ誰でもアクセス可能である必要があります。一部のビューは、魔法使いのみに制限されています。

class ProfileView(View): 
    @method_decorator(user_passes_test(has_profile)) 
    def dispatch(self, *args, **kwargs): 
     return super().dispatch(*args, **kwargs) 

class SorcererView(ProfileView): 
    @method_decorator(user_passes_test(is_a_sorcerer)) 
    def dispatch(self, *args, **kwargs): 
     return super().dispatch(*args, **kwargs) 

しかし、継承に、is_a_sorcererhas_profileと呼ばれてエラーとなりますのでご注意。

それはis_a_sorcererhas_profileをチェックすることが可能である:これはエラーを修正しながら

def is_a_sorcerer(user): 
    return has_profile(user) and user.profile.category == 'sorcerer' 

、それは二回has_profileをチェックし、その結果、およびチェックの二つ以上のレベルのオーバーヘッドが急速に蓄積します。

コードを複製せずにこれらのデコレータを作成するにはどうすればよいですか?私は依然として権限チェックを関数として保持して、関数ベースのビューに適用できるようにしたいと考えています。

+1

その継承の問題は何ですか?ユーザーにプロフィールがない場合、それは魔術師になることはできません。 'is_a_sorcerer'実装では、' has_profile 'もチェックする必要があります。 – afilardo

+0

[権限](https://docs.djangoproject.com/ja/1.10/topics/auth/customizing/#custom-permissions)を使用することはできませんか? – afilardo

+0

ビューに 'permission_required'デコレータを追加すると、' user_passes_test'と違うことはなく、依然としてパーミッションを2回チェックする必要があります。 – Koterpillar

答えて

1

実際にはis_a_sorcererメソッドでhas_profileをチェックします。 has_profileを2回確認するオーバーヘッドはごくわずかです。

def is_a_sorcerer(user): 
    return has_profile(user) and user.profile.category == 'sorcerer' 

チェックを2回実行することはできませんが、デコレータを使用することはできません。代わりに、ProfileViewを変更してテストのリストをチェックすることができます。次に、サブクラス内のテストのリストをオーバーライドします。

これはあまり一般的ではなく、おそらくはより壊れやすい/エラーが発生しやすいことに注意してください。サブクラスにuser_testsを上書きするときには、ProfileView.user_testsを含めるのを忘れやすいでしょう。

+0

実際には、デコレータは必ずしもキャッシュされていないデータベース呼び出しを実行します。 'user_tests'アプローチは、私が考えていたものです。デフォルトではありません。 – Koterpillar

関連する問題