use of python super function in django model

user637965 picture user637965 · Aug 22, 2011 · Viewed 28.5k times · Source

Here's some code in a django tutorial that I'm going through. I've never come across the super function in python before and the way it's used here is different from the examples I've seen online. I.e., usually when you use super, don't you have multiple classes? It's in the last line: super(Snippet, self).save(force_insert, force_update) Could you explain exactly what's going on there and what would be an alternative way to write that. It just seems like the save method is calling itself here?

class Snippet(models.Model):
    title = models.CharField(max_length=255)
    language = models.ForeignKey(Language)
    author = models.ForeignKey(User)
    description = models.TextField()
    description_html = models.TextField(editable=False)
    code = models.TextField()
    highlighted_code = models.TextField(editable=False)
    tags = TagField()
    pub_date = models.DateTimeField(editable=False)
    updated_date = models.DateTimeField(editable=False)

    class Meta:
        ordering = ['-pub_date']

    def __unicode__(self):
        return self.title

    def save(self, force_insert=False, force_update=False):
        if not self.id:
            self.pub_date = datetime.datetime.now()
        self.updated_date = datetime.datetime.now()
        self.description_html = markdown(self.description)
        self.highlighted_code = self.highlight()
        super(Snippet, self).save(force_insert, force_update)

Answer

unutbu picture unutbu · Aug 22, 2011

super(Snippet, self) causes Python to look in the MRO of the class of self (i.e. self.__class__.mro() for the next class listed after Snippet. It returns a super object which acts as a proxy for that class. That is, calling a method on the super object acts like calling that method on the class.

super(Snippet, self).save(...) calls that class's save method, with self bound to the first argument.

So super(Snippet, self).save(...) will not call Snippet's save method; it will call some other class's save method. It is tempting to think this "other class" is the "parent class" or "superclass" of Snippet, that is, models.Model, but that may not be true and it is absolutely wrong to apprehend super this way. Which class super(Snippet, self) ultimately represents depends on self and in particular its class's MRO.

A very good description of the MRO and super (complete with pictures!) can be found here.