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 が提案したように、パセリ デコレータを拡張すると、自分自身を呼び出し続ける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(...)。次に、この 2 番目のクラスがデコレータから返されます。

返されたクラス ( Bar) は name に割り当てられAccountFormます。

したがって、AccountFormオブジェクトを作成すると、 type のオブジェクトが作成されますBar。それを呼び出す.save(...)と、Bar.save実際にはFoo.saveから継承されFoo、オーバーライドされていないためです。

前に述べたように、 をFoo.save呼び出しますsuper(AccountForm, self).save(...)問題は、クラス デコレータが原因で、 isn ではAccountFormなくFoo、それがBar- であり、Bar親が is であることですFoo

したがって、の親をFoo.save検索すると、... になります。これは、その親を呼び出そうとすると、実際には自分自身を呼び出すことになるため、無限の再帰が発生することを意味します。AccountFormFoo.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 の save メソッドを次のように変更します。

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

違いがわからないことの1つは、super(Class, self)vssuper(Parent, self)私はこの質問をしたことです

于 2013-02-07T04:42:00.817 に答える