Shiva Krishna Bavandla
Shiva Krishna Bavandla

Reputation: 26668

clarification/when/where to use super in django/python

Actually we know super is used to find the "parent class" and return its object, something like/using self.__class__.__mro__

What I was confused about is when to use it exactly?

Suppose we have a Example model code as below

version_1

class Example(models.Model):
    name = models.CharField()
    age  = models.IntegerField()

    def save(self, **args, **kwargs):
        obj = super(Example, self).save(self, **args, **kwargs)
        obj.name = "name changed"
        obj.age = "age changed"
        return obj

version_2

class Example(models.Model):
    name = models.CharField()
    age  = models.IntegerField()

    def save(self, **args, **kwargs):
        self.name = "name changed"
        self.age = "age changed"
        obj = super(Example, self).save(self, **args, **kwargs)
        return obj

so as we can observe above

In version_1 I have called super first and done modifications to fields and returned the obj

In version_2 I had modified the fields and after that called super and returned obj

So what happens when super is called before and after modification of fields?

Finally what i want to know/confirm is

Upvotes: 7

Views: 9649

Answers (3)

Ricola3D
Ricola3D

Reputation: 2442

You call super:

  • first if the parent's method fills attributes you need in your treatment
  • last if you change the value of some attributes and want to apply the parent's method treatment with those new values

In conclusion, when you wanna change the implementation of a parent method:

  • Go to the parent's method implementation. Check what is done. Your IDE probably eases the job of retrieving the parent implementation, otherwise go to your Django install directory, then to /lib/python/site-packages/django and find the implementation by yourself.
  • According to your need (=use an attribute generated by the parent method OR change the value of an attribute used by the parent method) use super before OR after your custom code.

Upvotes: 3

Jay
Jay

Reputation: 2569

Your Example class is a subclass of Model. That means, that Example inherits all functions from Model.

Look at the following:

class Example():
    pass

example = Example()
#let's try to save it
example.save()

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: Example instance has no attribute 'save'

Now with inheritance.

class Parent():
    def save(*args, **kwargs):
        print "saving now"

class Example(Parent):
    pass

example = Example()
#since Example has no save method, it inherits the Parent's save method.
example.save()
"saving now"

If you override the save() method in your Example class, the Parent's save method will not be called.

   class Example(Parent):
        def save(self, *args, **kwargs):
            print "i know how to save on my own now"

   example = Example()
   example.save()
   "i know how to save on my own now"

If you choose to call super, you are calling the Parent's save function together with your own implementation of save().

   class Example(Parent):
         def save(self, *args, **kwargs):
              super(Example, self).save(*args, **kwargs)
              print "i know how to save on my own now"

   example = Example()
   example.save()
   "saving now" #from parent
   "i know how to save on my own" #from example

The same applies to all of djangos classes you inherit from. In fact, the implementation is more complex. You can take a look at the Model definition here on github.

If you feel thrilled, you can dive into the django ORM with this talk

Upvotes: 22

siebz0r
siebz0r

Reputation: 20339

I believe this question in not Django specific, therefore I will try to explain it in a generic way.

The practicality of super is that you do not need to specify which base class is to be called (this can also be a downside because the mro defines what base class is called).

I use super to create mixins (there is an excellent answer on SO that describes what a mixin is). An example that uses super:

class LemonMixin(object):
    def tastes_like(self):
        return super(LemonMixin, self).tastes_like() + ' and lemon'

class Cola(object):
    def tastes_like(self):
        return 'sugar'

class ColaLemon(LemonMixin, Cola):
    pass

drink = ColaLemon()
drink.tastes_like()  # returns 'sugar and lemon'

The mixin is agnostic of the aplied class so it can use super to use the mro to call a base class.

When to call super is totally up to you. If you, for example, want to check for security you call super after the security checks. If you want to fire an event when something finished, you may want to call super before firing the event. ;-)

Upvotes: 6

Related Questions