Erik Åsland
Erik Åsland

Reputation: 9782

Django/Python: understanding how super is used in function

I am just beginning to wrap my head around what super is and how it is implemented in view based classes in Django. I am trying to understand how super is working in the following code. Could someone try to break it down for me piece by piece?

from django.views.generic.detail import DetailView
from apps.app_name.models import Article

class ArticleDetailView(DetailView):
    model = Article
    template_name = 'article/show.html'

    def get_context_data(self, **kwargs):
        context = super(ArticleDetailView, self).get_context_data(**kwargs)
        return context

Upvotes: 4

Views: 3463

Answers (2)

wim
wim

Reputation: 362786

As currently written, the method does absolutely nothing and could be removed.

The context data method is directly delegated to the next class in the inheritance chain. In this case, it would mean the superclass DetailView.get_context_data is used.

However, this would happen anyway if the method was not present on ArticleDetailView. So it's pointless to write it like that, passing onto the superclass explicitly.

So, the code is just strange - does this answer your question?


If you actually wanted to do something different in the subclass, for example, then it would make sense to implement this method. For example:

def get_context_data(self, **kwargs):
    context = super(ArticleDetailView, self).get_context_data(**kwargs)
    context['new_key'] = 'some injected context from ArticleDetailView'
    return context

Then we are using the context data from DetailView, and adding additional context in ArticleDetailView.

The reason to use super(ArticleDetailView, self).get_context_data instead of just simply using DetailView.get_context_data directly is complicated, and related to the method resolution order (MRO). It's explained in some detail by Raymond Hettinger over here.

Note: in python 3 the implementation of super is cleaned up a bit, and you no longer need super(ArticleDetailView, self) you can just use super() thankfully.

Upvotes: 5

Gocht
Gocht

Reputation: 10256

The super method will access to the current class and call an specific method, in this case:

super(ArticleDetailView, self)  # Access to the current class

And execute an specific method:

.get_context_data(**kwargs)

The .get_context_data() method in a View class, returns the context passed to the template (.html file). In this case, you're using a DetailView, so you have some predefined context, such as: object or article.

If you just override .get_context_data() without calling .super(), like this:

def get_context_data(self, **kwargs):
    my_context = {...}
    return my_context

You will lost the predefined variables in the DetailView context. But if you want to add some new variables (values) to the current DetailView's context, you need the original context, and that's what super(ArticleDetailView, self).get_context_data(**kwargs) will give you. So you will use it in this way:

def get_context_data(self, **kwargs):
    context = super(ArticleDetailView, self).get_context_data(**kwargs)
    context.update({'my_key': 'my_value'})
    return context

Now you will be able to use your own value in the template without losing the default DetailView's context values.

Upvotes: 7

Related Questions