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

查看:230
本文介绍了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

它按预期工作:当匿名用户访问页面时,dispatch方法调用.py#L45"rel =" noreferrer> 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)

在某些情况下不起作用,因为尚未调用视图继承的mixins的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中包含一些更复杂的逻辑:它检查权限,进行一些计算并将其存储在class属性中,等等.

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天全站免登陆