问题描述
通常,我使用基于类的视图的 dispatch
方法来设置一些初始变量或根据用户的权限添加一些逻辑.
Normally, I use a dispatch
method of a class based view to set some initial variables or add some logic based on user's permissions.
例如
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
它按预期工作:当匿名用户访问页面时, 被调用,然后将用户重定向到登录页面.
It works as expected: when an anonymous user visits a pages, the dispatch
method of LoginRequiredMixin is called, and then redirects the user to the login page.
但是如果我想为此视图添加一些权限或设置一些初始变量,例如,
But if I want to add some permissions for this view or set some initial variables, for example,
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
重复验证:
in some cases it doesn't work, because dispatch
methods of the mixins, that the view inherits, haven't been called yet. So, for example, to be able to ask for user's permissions, I have to repeat the validation from 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中有一些更复杂的逻辑:检查权限,进行一些计算并将其存储在类属性中等.
This example is simple, but sometimes there are some more complicated logic in a mixin: it checks for permissions, makes some calculations and stores it in a class attribute, etc.
现在我通过从 mixin 复制一些代码(如上面的示例中)或通过将视图的 dispatch
方法中的代码复制到另一个 mixin 并在第一个之后继承它来解决它一个按顺序执行它们(这不是那么漂亮,因为这个新的 mixin 只被一个视图使用).
For now I solve it by copying some code from the mixin (like in the example above) or by copying the code from the dispatch
method of the view to another mixin and inheriting it after the first one to execute them in order (which is not that pretty, because this new mixin is used only by one view).
有什么好的方法可以解决这些问题吗?
Is there any proper way so solve these kind of problems?
推荐答案
我会写自定义类,检查所有权限
I would write custom class, which check all permissions
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(SuperOrManagerPermissionsMixin, FormView) 的实现不需要重写调度方法
And implementation of class GenerateReportView(SuperOrManagerPermissionsMixin, FormView) does not require overriding dispatch method
如果使用多重继承,其中一个父类需要改进,最好先改进.它使代码更干净.
If you use multiple inheritance and one of the parent classes need some improvement, it's good to improve it first. It keeps code cleaner.
这篇关于Django:一个基于类的视图,带有 mixins 和 dispatch 方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!