What you could do is just call the parent's method directly:
@parsleyfy
class AccountForm(forms.ModelForm):
def save(self, *args, **kwargs):
# some other code...
return forms.ModelForm.save(self, *args,**kwargs)
This should neatly avoid the issue introduced by your class decorator. Another option would be to manually call the decorator on a differently named base class, rather than using @
syntax:
class AccountFormBase(forms.ModelForm):
def save(self, *args, **kwargs):
# some other code...
return super(AccountFormBase, self).save(*args,**kwargs)
AccountForm = parsleyfy(AccountFormBase)
However, you might also want to consider using a pre-save signal instead, depending on what you're trying to do - it's how one normally adds functionality that should happen before the rest of the model save process in Django.
As for why this is occurring, consider what happens when the code is evaluated.
First, a class is declared. We'll refer to this original class definition as Foo
to distinguish it from the later class definition that the decorator will create. This class has a save
method which makes a super(AccountForm, self).save(...)
call.
This class is then passed to the decorator, which defines a new class which we'll call Bar
, and inherits from Foo
. Thus, Bar.save
is equivalent to Foo.save
- it also calls super(AccountForm, self).save(...)
. This second class is then returned from the decorator.
The returned class (Bar
) is assigned to the name AccountForm
.
So when you create an AccountForm
object, you're creating an object of type Bar
. When you call .save(...)
on it, it goes and looks up Bar.save
, which is actually Foo.save
because it inherited from Foo
and was never overridden.
As we noted before, Foo.save
calls super(AccountForm, self).save(...)
. The problem is that because of the class decorator, AccountForm
isn't Foo
, it's Bar
- and Bar
's parent is Foo
.
So when Foo.save
looks up AccountForm
's parent, it gets... Foo
. This means that when it tries to call .save(...)
on that parent, it actually just winds up calling itself, hence the endless recursion.