繁体   English   中英

如何向基于Django类的通用视图装饰器添加参数?

[英]How to add parameters to Django class based generic view decorators?

我写了一个装饰器来显示对象创建的成功消息:

from django.contrib import messages

def success_message(klass):
    def form_valid(self, form):
        response = super(klass, self).form_valid(form)
        messages.success(self.request, 'Object added successfully')
        return response

    klass.form_valid = form_valid
    return klass

并使用它来装饰基于类的通用视图:

@success_message
class BandCreateView(CreateView):
    model = Band

现在我想参数化装饰器,所以这是可能的:

@success_message('Band created successfully.')
class BandCreateView(CreateView):
    model = Band

我该怎么做? 我尝试将message参数添加到success_message但是编译器抱怨参数计数不匹配所以我认为必须有另一种方法。

看起来你必须使用闭包:

def decorator(arg):
    def wrap(klass): ...
    return wrap

因为您的电话被评估为

class BandCreateView(CreateView): ...
BandCreateView = @success_message('Band created successfully.')(BandCreateView)

请注意双重通话

我以前做过这样的事情就像mixin一样,但是装饰器更有意义(并且添加到类中有点麻烦)。 您可能希望获得表单实例的详细名称,如下所示,以消除将消息传递给装饰器的需要:

from django.utils.translation import ugettext_lazy as _

def ucfirst(value):
    return value[0].upper() + value[1:]

def success_message(klass):
    __orig_form_valid = klass.form_valid
    def form_valid(self, form):
        response = __orig_form_valid(self, form)
        messages.success(self.request, _("%(object)s \"%(object_name)s\" was saved successfully.") %
                         {'object': ucfirst(form.instance._meta.verbose_name), 'object_name': unicode(form.instance)})
        return response

    klass.form_valid = form_valid
    return klass

这将产生一条成功信息:

客户“ACME Inc.” 已成功保存。

TL; DR

无参数装饰器被声明为class -> class函数。
带参数的Decorator被声明为更高阶的args -> (class -> class)函数。

它接受参数并返回一个函数,它将获取类和返回类 (即“简单”装饰器)。

说明

来自t.dubrownik相关主题答案字面上救了我。

无论如何,带参数的装饰器的语法有点不同 - 带参数的装饰器应返回一个函数,该函数将接受一个函数并返回另一个函数 所以它应该真正返回一个普通的装饰器。

虽然他在讨论函数装饰器,但这个概念也适用于类装饰器。
这是我得到的:

from django.contrib import messages

def success_message(message):
    def actual_decorator(klass):
        def form_valid(self, form):
            response = super(klass, self).form_valid(form)
            messages.success(self.request, message)
            return response

        klass.form_valid = form_valid
        return klass

    return actual_decorator

注意如何actual_decorator本身重复的无参数版本success_message以及如何success_message现在是一个高阶的功能,因为它的返回值是函数本身。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM