2015-01-07 3 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 유지 mixin 방법,보기 그 때문에 상속받은 자들이 아직 부름을받지 못했다.

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) 

이 예제는 간단하지만, 때로는 혼합에 좀 더 복잡한 논리가 있습니다 : 그래서, 예를 들어, 사용자의 권한을 요청할 수 있도록, 나는 LoginRequiredMixin에서 유효성 검사를 반복 할 필요가를 확인 일부 계산을 수행하고 클래스 속성에 저장합니다.

이제는 mixin에서 일부 코드를 복사하거나 (위의 예처럼) 코드를 dispatch보기에서 복사하여 해결합니다. 다른 믹스 인에게 보내고 순서대로 실행하려면 첫 번째 믹스 인을 이어 받아야합니다. (이 새로운 믹스 인은 하나의보기에서만 사용되기 때문에 그다지 좋지 않습니다.)

이러한 문제를 해결할 수있는 적절한 방법이 있습니까?

+0

처음''super (GenerateReportView, self) .dispatch (* args, ** kwargs)''를 호출하십시오. –

+2

@MihaiZamfir 예를 들어''LoginRequiredMixin''는''HttpResponseRedirect'' 객체를 반환하기 때문에 작동하지 않을 것입니다. 그래서 우리가 변수에 저장한다면, 우리가이 변수를''dispatch'' 메소드의 끝에서 반환 할 때까지 로그인 뷰로 리디렉션하지 않습니다. – vero4ka

+0

하지만 응답이 리디렉션인지 확인한 다음 디스패치를 ​​계속 수행 할 수 있습니다. –

답변

1

예를 들어, UserPassesTestMixindjango-braces에서 사용합니다. 즉 당신의 더 복잡한 논리에 적합하지 않은 경우가 잘 복잡한 로직을 캡슐화로

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

후 별도의 믹스 인을 만드는 것은, OK의 방법처럼 들린다. 장고 1.9으로

편집

는 UserPassesTestMixin 이제 장고에 포함되어 있습니다 : 나는 모든 권한
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) 

그리고 클래스 GenerateReportView의 구현을 확인 사용자 정의 클래스를 작성합니다

2

이것은 오래된 게시물이지만 다른 사람들이 올 수 있으므로 여기에 제안 된 해결책이 있습니다.

당신이 말할 때

"[

...] 내가 예를 들어 [...] "

대신보기의 발송 방법에 그 초기 변수를 설정하는 경우,이보기 또는 세트의 일부 초기 변수에 대한 몇 가지 권한을 추가하려면, 당신은 쓸 수 이러한 변수를 설정하는 분리 된 메서드를 호출 한 다음 get (및 필요한 경우 게시) 메서드에서 해당 메서드를 호출하면 디스패치 후에 호출되므로 초기 변수를 설정하는 것은 믹스의 디스패치와 충돌하지 않습니다. 방법

def set_initial_variables(): 
    self.hey = something 
    return 

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

이것은 아마도 copyi보다 더 깨끗합니다. 보기의 디스패치에서 믹스 인 코드를 붙여 넣을 수 있습니다.

관련 문제