Django:一个基于类的视图,带有 mixins 和 dispatch 方法 [英] Django: a class based view with mixins and dispatch method

查看:28
本文介绍了Django:一个基于类的视图,带有 mixins 和 dispatch 方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

通常,我使用基于类的视图的 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

它按预期工作:当匿名用户访问页面时,LoginRequiredMixin 被调用,然后将用户重定向到登录页面.

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 方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆