dispatch
方法来设置一些初始变量或基于用户权限添加一些逻辑。例如,
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
它按预期工作:当匿名用户访问页面时,LoginRequiredMixin的dispatch
方法被调用,然后将用户重定向到登录页面。
但是如果我想为此视图添加一些权限或设置一些初始变量,例如:
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)
在某些情况下,它可能无法正常工作,因为视图继承的 mixin 的 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 中会有一些更复杂的逻辑:检查权限、进行一些计算并将其存储在类属性中等等。
目前我通过从 mixin 中复制一些代码(就像上面的例子中那样)或者将视图的 dispatch
方法的代码复制到另一个 mixin 中,并在第一个 mixin 之后继承它以按顺序执行它们来解决这个问题(这不太好看,因为这个新的 mixin 只被一个视图使用)。
有没有什么正确的方法来解决这些问题?
super(GenerateReportView, self).dispatch(*args, **kwargs)
,然后在你重写的 dispatch 方法内完成其余工作。 - Mihai Zamfir