5

我正在覆盖 a 的 save 方法,但ModelForm我不知道它为什么会导致递归:

@parsleyfy
class AccountForm(forms.ModelForm):
    def save(self, *args, **kwargs):
        # some other code...
        return super(AccountForm, self).save(*args,**kwargs)

导致这个:

maximum recursion depth exceeded while calling a Python object

Stacktrace 显示此行重复调用自身:

return super(AccountForm, self).save(*args,**kwargs) 

现在,欧芹装饰器是这样的:

def parsleyfy(klass):
    class ParsleyClass(klass):
      # some code here to add more stuff to the class
    return ParsleyClass

正如@DanielRoseman 建议Parsley 装饰器扩展AccountForm原因super(AccountForm,self)以继续调用自身,解决方案是什么?

我也无法理解为什么这会导致递归。

4

2 回答 2

6

你可以做的就是直接调用父母的方法:

@parsleyfy
class AccountForm(forms.ModelForm):
    def save(self, *args, **kwargs):
        # some other code...
        return forms.ModelForm.save(self, *args,**kwargs)

这应该可以巧妙地避免您的类装饰器引入的问题。另一种选择是在不同命名的基类上手动调用装饰器,而不是使用@语法:

class AccountFormBase(forms.ModelForm):
    def save(self, *args, **kwargs):
        # some other code...
        return super(AccountFormBase, self).save(*args,**kwargs)

AccountForm = parsleyfy(AccountFormBase)

但是,您可能还想考虑使用预保存信号,这取决于您要尝试做什么 - 这是一个通常应该在 Django 中的模型保存过程的其余部分之前发生的添加功能的方式。


至于为什么会发生这种情况,请考虑评估代码时会发生什么。

首先,声明一个类。我们将引用这个原始类定义,Foo以将其与装饰器将创建的后续类定义区分开来。这个类有一个调用的save方法。super(AccountForm, self).save(...)

然后这个类被传递给装饰器,它定义了一个我们将调用的新类Bar,并继承自Foo。因此,Bar.save等价于Foo.save- 它也调用super(AccountForm, self).save(...). 然后从装饰器返回第二个类。

返回的类 ( Bar) 分配给 name AccountForm

因此,当您创建一个AccountForm对象时,您正在创建一个类型为 的对象Bar。当你调用.save(...)它时,它会向上查找Bar.save,这实际上是Foo.save因为它继承自Foo并且从未被覆盖。

正如我们之前提到的,Foo.save调用super(AccountForm, self).save(...). 问题是由于类装饰器,AccountFormis not Foo,它是Bar- 并且Bar's parent is Foo

因此,当Foo.save查找AccountForm的父母时,它会Foo...... 这意味着当它试图调用.save(...)那个父对象时,它实际上只是调用了自己,因此是无休止的递归。

于 2013-02-07T05:12:59.030 回答
0

这是我为使其工作所做的工作,我可以更改 parsleyfy 类以覆盖保存方法,如下所示:

def parsleyfy(klass):
    class ParsleyClass(klass):
        def save(self, *args, **kwargs):
            return super(klass, self).save(*args, **kwargs)
    return ParsleyClass

或将 AccountForm 的保存方法更改为:

@parsleyfy
class AccountForm(forms.ModelForm):
    def save(self, *args, **kwargs):
        return super(forms.ModelForm, self).save(*args,**kwargs)

我没有什么区别的一件事是super(Class, self)vssuper(Parent, self)我问过这个问题

于 2013-02-07T04:42:00.817 回答