Jam*_*Lin 5 python forms django recursion save
我正在覆盖a的save方法,ModelForm我不知道它为什么会导致递归:
@parsleyfy
class AccountForm(forms.ModelForm):
def save(self, *args, **kwargs):
# some other code...
return super(AccountForm, self).save(*args,**kwargs)
Run Code Online (Sandbox Code Playgroud)
导致这个:
maximum recursion depth exceeded while calling a Python object
Run Code Online (Sandbox Code Playgroud)
Stacktrace显示此行反复调用自身:
return super(AccountForm, self).save(*args,**kwargs)
Run Code Online (Sandbox Code Playgroud)
现在,欧芹装饰器是这样的:
def parsleyfy(klass):
class ParsleyClass(klass):
# some code here to add more stuff to the class
return ParsleyClass
Run Code Online (Sandbox Code Playgroud)
正如@DanielRoseman所说的那样,Parsley装饰器扩展了AccountForm导致它super(AccountForm,self)不断调用自己,解决方案是什么?
此外,我无法理解为什么这会导致递归.
你能做的就是直接调用父方法:
@parsleyfy
class AccountForm(forms.ModelForm):
def save(self, *args, **kwargs):
# some other code...
return forms.ModelForm.save(self, *args,**kwargs)
Run Code Online (Sandbox Code Playgroud)
这应该整齐地避免您的类装饰器引入的问题.另一种选择是在不同命名的基类上手动调用装饰器,而不是使用@语法:
class AccountFormBase(forms.ModelForm):
def save(self, *args, **kwargs):
# some other code...
return super(AccountFormBase, self).save(*args,**kwargs)
AccountForm = parsleyfy(AccountFormBase)
Run Code Online (Sandbox Code Playgroud)
但是,您可能还需要考虑使用预保存信号,具体取决于您尝试执行的操作 - 通常会添加在Django中的其余模型保存过程之前应该发生的功能.
至于为什么会发生这种情况,请考虑在评估代码时会发生什么.
首先,声明一个类.我们将引用这个原始类定义,Foo以区别于装饰器将创建的后面的类定义.这个类有save一个super(AccountForm, self).save(...)调用方法.
然后将该类传递给装饰器,装饰器定义了一个我们将调用Bar并继承自的类Foo.因此,Bar.save相当于Foo.save- 它也调用super(AccountForm, self).save(...).然后从装饰器返回第二个类.
返回的class(Bar)被分配给名称AccountForm.
因此,在创建AccountForm对象时,您将创建一个类型的对象Bar.当你调用.save(...)它时,它会查找Bar.save,这实际上是Foo.save因为它继承Foo并且从未被覆盖.
正如我们之前提到的,Foo.save电话super(AccountForm, self).save(...).问题是因为类装饰器,AccountForm不是Foo,它是Bar- 而且Bar是父级的Foo.
所以,当Foo.save查找AccountForm的母公司,它得到... Foo.这意味着当它试图调用.save(...)那个父级时,它实际上只是最终调用自身,因此无休止的递归.