我编写了一个装饰器来显示对象创建的成功消息:
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
但是编译器抱怨参数计数不匹配,所以我认为必须有另一种方法。
答案 0 :(得分:3)
看起来你必须使用闭包:
def decorator(arg):
def wrap(klass): ...
return wrap
因为你的电话被评估为
class BandCreateView(CreateView): ...
BandCreateView = @success_message('Band created successfully.')(BandCreateView)
请注意双重调用
答案 1 :(得分:1)
我以前做过这样的事情就像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.”已成功保存。
答案 2 :(得分:0)
无参数装饰器被声明为 class -> class
功能
带参数的装饰器被声明为高阶 args -> (class -> class)
函数。
它接受参数并返回一个函数,该函数将获取类和返回类(即“简单”装饰器)。
related thread 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
现在是一个更高阶函数,因为它的返回值是函数本身。