您可以做的就是直接调用父级的方法:
@parsleyfy
class AccountForm(forms.ModelForm):
def save(self, *args, **kwargs):
# some other code...
return forms.ModelForm.save(self, *args,**kwargs)
这应该巧妙地避免类装饰器引入的问题。另一种选择是在不同名称的基类上手动调用装饰器,而不是使用@
syntax:
class AccountFormBase(forms.ModelForm):
def save(self, *args, **kwargs):
# some other code...
return super(AccountFormBase, self).save(*args,**kwargs)
AccountForm = parsleyfy(AccountFormBase)
但是,您可能还想考虑使用预存信号 https://docs.djangoproject.com/en/dev/ref/signals/#pre-save相反,取决于您想要做什么 - 这通常是添加功能的方式,这些功能应该在 Django 中模型保存过程的其余部分之前发生。
As for why发生这种情况时,请考虑计算代码时会发生什么。
首先,声明一个类。我们将这个原始类定义称为Foo
以将其与装饰器将创建的后续类定义区分开来。这个类有一个save
方法使得super(AccountForm, self).save(...)
call.
然后这个类被传递给装饰器,它定义了一个我们称之为的新类Bar
,并继承自Foo
. Thus, Bar.save
相当于Foo.save
- 它还调用super(AccountForm, self).save(...)
。然后从装饰器返回第二个类。
返回的类(Bar
) 被分配给名称AccountForm
.
所以当你创建一个AccountForm
对象,您正在创建一个类型的对象Bar
。你打电话时.save(...)
在它上面,它会抬起头来Bar.save
,这实际上是Foo.save
因为它继承自Foo
并且从未被覆盖。
正如我们之前指出的,Foo.save
calls super(AccountForm, self).save(...)
. 问题是由于类装饰器,AccountForm
isn't Foo
, it's Bar
- and Bar
的父母是Foo
.
So when Foo.save
仰望;查询AccountForm
的父母,它得到...Foo
。这意味着当它尝试调用.save(...)
在那个父级上,它实际上只是最终调用自己,因此是无休止的递归。