【发布时间】:2015-03-05 15:02:11
【问题描述】:
通常,我使用基于类的视图的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)
在某些情况下它不起作用,因为尚未调用视图继承的 mixins 的 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 之后继承它来解决它以执行它们order(这不是很漂亮,因为这个新的 mixin 只被一个视图使用)。
有什么合适的方法可以解决这类问题吗?
【问题讨论】:
-
第一次致电
super(GenerateReportView, self).dispatch(*args, **kwargs)。然后在您覆盖的调度中完成其余的工作 -
@MihaiZamfir 它不起作用,因为例如
LoginRequiredMixin返回一个HttpResponseRedirect对象,所以如果我们将它存储在一个变量中,它不会重定向到登录视图直到我们在dispatch方法结束时返回这个变量。 -
但您可以检查响应是否为重定向,然后继续调度
-
问题是混入的上游处理可能会导致有效的重定向。例如。有像(LoginRequiredMixin,CustomViewWhichRedirectsSometimes)这样的继承层次结构,现在,如果需要登录的调度返回重定向,我们需要以某种方式判断是因为用户未授权还是完全预期的来自 CustomViewWhichRedirectsSometimes 的重定向。
标签: django django-views mixins