1

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
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
w--
  • 6,427
  • 12
  • 54
  • 92
  • calling super method looks right, are you sure there isn't more or different code? also instead of `object` use 'obj' – Anurag Uniyal Apr 17 '10 at 05:05
  • thanks for the tip to use obj. I don't know if there is supposed to be more code, that is all there is at the link. The commenter at the link might be assuming that who ever is reading it is way more proficient at django/python than i am and that the missing bits are obvious? – w-- Apr 17 '10 at 17:44

2 Answers2

3

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
  • 32,032
  • 8
  • 79
  • 100
  • 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-- May 01 '10 at 05:38
  • 1
    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 May 03 '10 at 07:08
0

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?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
maersu
  • 3,242
  • 22
  • 27
  • 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-- Apr 29 '10 at 08:33