2015-01-07 26 views
18

通常、クラスベースのビューのdispatchメソッドを使用して、いくつかの初期変数を設定したり、ユーザーの権限に基づいてロジックを追加したりします。例えばDjango:mixinsとディスパッチメソッドを持つクラスベースのビュー

、予想通り

from django.views.generic import FormView 
from braces.views import LoginRequiredMixin 

class GenerateReportView(LoginRequiredMixin, FormView): 
    template_name = 'reporting/reporting_form.html' 
    form_class = ReportForm 

    def get_form(self, form_class): 
     form = form_class(**self.get_form_kwargs()) 
     if not self.request.user.is_superuser: 
      form.fields['report_type'].choices = [ 
       choice for choice in form.fields['report_type'].choices 
       if choice[0] != INVOICE_REPORT 
      ] 
     return form 

それは動作します:匿名ユーザーがページを訪れたとき、LoginRequiredMixindispatchメソッドが呼び出され、その後、ログインページにユーザーをリダイレクトしています。

しかし、私は、それが動作しないいくつかのケースでは

class GenerateReportView(LoginRequiredMixin, FormView): 

    def dispatch(self, *args, **kwargs): 
     if not (
      self.request.user.is_superuser or 
      self.request.user.is_manager 
     ): 
      raise Http404 
     return super(GenerateReportView, self).dispatch(*args, **kwargs) 

、例えば、このビューのいくつかの権限を追加したり、いくつかの初期の変数を設定したい場合はdispatchミックスインの方法、眺めているので、継承は、まだ呼び出されていません。したがって、たとえば、ユーザーの権限を求めることができるように、私はLoginRequiredMixinから検証を繰り返す必要があります。

class GenerateReportView(LoginRequiredMixin, FormView): 

    def dispatch(self, *args, **kwargs): 
     if self.request.user.is_authenticated() and not (
      self.request.user.is_superuser or 
      self.request.user.is_manager 
     ): 
      raise Http404 
     return super(GenerateReportView, self).dispatch(*args, **kwargs) 

この例は単純ですが、時には混合でいくつかのより複雑なロジックがあります。それはをチェック

今のところ私はmixinからいくつかのコードをコピーするか(上記の例のように)、ビューのdispatchメソッドからコードをコピーすることで解決します別のミックスインに転送し、最初のミックスを継承して順番に実行します(これは、新しいミックスインが1つのビューでのみ使用されるためです)。

このような問題を解決する方法はありますか?

+0

最初に '' super(GenerateReportView、self).dispatch(* args、** kwargs) ''を呼び出します。 –

+2

@MihaiZamfirたとえば、 '' LoginRequiredMixin''が '' HttpResponseRedirect''オブジェクトを返すので、これは動作しません。変数に格納する場合は、 '' dispatch''メソッドの最後にこの変数を返すまで、ログインビューにリダイレクトされません。 – vero4ka

+0

ですが、応答がリダイレクトであるかどうかを確認してから、ディスパッチを続行してください。 –

答えて

3

私は(すべての権限クラスGenerateReportViewの

from django.views.generic import FormView 
from braces.views import AccessMixin 

class SuperOrManagerPermissionsMixin(AccessMixin): 
    def dispatch(self, request, *args, **kwargs): 
     if not request.user.is_authenticated(): 
      return self.handle_no_permission(request) 
     if self.user_has_permissions(request): 
      return super(SuperOrManagerPermissionsMixin, self).dispatch(
       request, *args, **kwargs) 
     raise Http404 #or return self.handle_no_permission 

    def user_has_permissions(self, request): 
     return self.request.user.is_superuser or self.request.user.is_manager 

# a bit simplyfied, but with the same redirect for anonymous and logged users 
# without permissions 


class SuperOrManagerPermissionsMixin(AccessMixin): 
    def dispatch(self, request, *args, **kwargs): 
     if self.user_has_permissions(request): 
      return super(SuperOrManagerPermissionsMixin, self).dispatch(
       request, *args, **kwargs) 
     else: 
      return self.handle_no_permission(request) 

    def user_has_permissions(self, request): 
     return request.user.is_authenticated() and (self.request.user.is_superuser 
                or self.request.user.is_manager) 


class GenerateReportView(SuperOrManagerPermissionsMixin, FormView): 
#Remove next two lines, don't need it 
    def dispatch(self, *args, **kwargs): 
     #or put some logic here 
     return super(GenerateReportView, self).dispatch(*args, **kwargs) 

と実装を確認した、カスタムクラスを記述しますSuperOrManagerPermissionsMixin、FormView)は、ディスパッチメソッドをオーバーライドする必要はありません

multip親クラスのうちの1つに何らかの改善が必要な場合は、まずそれを改善することをお勧めします。コードをよりきれいに保ちます。

1

あなたが与えた例では、UserPassesTestMixindjango-bracesから使用します。

class GenerateReportView(UserPassesTestMixin, FormView): 
    def test_func(self, user): 
     return user.is_superuser or user.is_manager 

それはあなたのより複雑なロジックに適していない場合、それはきれいに複雑なロジックをカプセル化して、その後、別のミックスインを作成することは、OKアプローチのように聞こえます。ジャンゴ1.9のよう

EDIT
、UserPassesTestMixinは現在、Djangoの中に含まれています:https://docs.djangoproject.com/en/1.11/topics/auth/default/#django.contrib.auth.mixins.UserPassesTestMixin

2

これは古い投稿ですが、他の人が出てくる可能性がありますので、私の提案する解決策です。

あなたは

を言います「[...]私が代わりにあなたのビューの発送方法でこれらの初期変数を設定するのでは、あなたが書くことができます例えば、いくつかの 初期変数、[...]」

を設定し、このビューのためのいくつかの権限を追加する場合、またはそれらの変数を設定するための分離されたメソッド、そしてあなたのget(そして必要に応じて投稿)メソッドでそのメソッドを呼び出すことができます。方法

def set_initial_variables(): 
    self.hey = something 
    return 

def get(blablabla): 
    self.set_initial_variables() 
    return super(blabla, self).get(blabla) 

これはおそらくコピーよりもクリーンですビューのディスパッチでミックスインのコードを貼り付けることができます。

関連する問題