views:

305

answers:

2

I was hunting around the Internet for a way to easily allow users to blank out imagefield/filefields they have set in the admin.

I found this: http://www.djangosnippets.org/snippets/894/.

What was really interesting to me here was the code posted in the comment by rfugger:

remove_the_file = forms.BooleanField(required=False)

def save(self, *args, **kwargs):
    object = super(self.__class__, self).save(*args, **kwargs)
    if self.cleaned_data.get('remove_the_file'):
        object.the_file = ''
    return object

When I try to use this in my own form I basically added this to my admin.py which already had a BlahAdmin.

class BlahModelForm(forms.ModelForm):
    class Meta:
        model = Blah

    remove_img01 = forms.BooleanField(required=False)

    def save(self, *args, **kwargs):
        object = super(self.__class__, self).save(*args, **kwargs)
        if self.cleaned_data.get('remove_img01'):
            object.img01 = ''
        return object

When I run it I get the error

maximum recursion depth exceeded while calling a Python object

at this line:

object = super(self.__class__, self).save(*args, **kwargs)

When I think about it for a bit, it seems obvious that it is just infinitely calling itself causing the error. My problem is I can't figure out what is the correct way I should be doing this. Any suggestions?

Additional information as requested:

Model of blah:

class Blah(models.Model):
    blah_name = models.CharField(max_length=25, unique=True)
    slug = models.SlugField()
    img01 = models.ImageField(upload_to='scenes/%Y/%m', blank=True)

    def __unicode__(self):
        return self.blah_name
A: 

I have tested it on my machine and it works :-) . I used exactly your piece of code. The problem has to be outside of this code.

Please post a snippet how you call/save the form and the declaration of the Model Blah.

Did you overwrite the save method of Model Blah?

maersu
hi maersu, thanks for your interest. i agree that it does sound like something outside the code.i don't do anything special to call the form, i'm just using it in django admin. i do not overwrite the save method of Model Blah.i've put the model for blah above.
w-
+1  A: 

Never use super(self.__class__, self)! Try the following example:

class A(object):
    def m(self):
        super(self.__class__, self).m()

class B(A): pass

B().m()

It will fail with the same error:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in m
  ... repeated a lot of times ...
RuntimeError: maximum recursion depth exceeded while calling a Python object

Let's see what's going on. You call A.m method for B instance, so self.__class__ is B and super(self.__class__, self).m refers to the same method A.m, so A.m calls itself instead of calling the method of base class. This leads to infinite recursion.

Denis Otkidach
Hey Denis,Thanks for your answer. yesterday i tried:**obj = super(BlahModelForm, self).save(\*args, \**kwargs)** and this works as expected. Thinking about it, shouldn't it have the same result as using **super(self.\__class\__, self).save(\*args, \**kwargs)**? In the first instance, it just seems that I am explicitly calling the name of the class i'm in, instead of going via **self.\__class\__**. Is there something obvious i'm missing here?
w-
When you use self.__class__ in a method of BlahModelForm, it is not guaranteed to give you BlahModelForm. self could be an instance of a different class (specifically a child/derived class of BlahModelForm). This is the situation that Denis' example illustrates.
zlovelady