[Fixed]-How does django's View class work

23👍

The underlying implementation of these views involves some fairly advanced Python, so if you’re a relative beginner it’s not surprising if you find some of this code confusing.

  1. The main thing you should understand is what the @classmethod decorator does on the definition of as_view(). This means that this method is not a normal method, which is called on an instance of the class (and takes the instance as the self parameter), but a classmethod, which is called on the class itself (and takes the class as the cls parameter). Some languages refer to that as a static method, although in Python that’s a third type of method that we don’t need to go into here.

  2. This is because of how the view is defined in the urlconf. You correctly put WelcomeView.as_view() – what this does is call the as_view classmethod at the time that the urlconf is imported.

  3. As we know from point 1, cls is the view class itself. As normal with a class, when you call it, you get an object. So, as you say, what we’re doing here is instantiating the class, then assigning that instance to a variable called self, as if we were inside a method of that instance. The point here is that as I said above, as_view is called at import time, and it returns a function – view – that is in turn called by the URL dispatcher when a browser requests that URL. So inside that function, we construct and call the rest of the class that makes up the class-based view. As to why it’s needed, see below.

  4. The __init__ method takes care of setting each member of initargs to an instance attribute, where you can access it in your view code via the usual self.whatever syntax.

So, why is all this necessary?

Class-based views come with a huge potential gotcha, which is that any class instantiated directly in the URLconf (or anywhere else at module level) will persist throughout the entire lifetime of the process. And the way that Django is commonly deployed – via WSGI – usually means that one process can last for many many requests. And if you have something persisting across multiple requests, you have the potential for some really nasty thread-safety bugs – if you set something to an instance attribute in one request, for example, it will be visible in subsequent requests.

So, this code not only ensures that each request gets a new instance, it also makes it really hard to break that request isolation by dynamically constructing the instance each time inside the view function.

2👍

1.
Firstly as_view() is a class method. This is a method that can be called on a class rather than an instance of a class. And in this case you can see it’s being call on View, which is a class rather than an instance.

2.
as_view() is called when the url.conf module is loaded – it returns the function view(). It’s this function that’s called every time a view is requested – as_view doesn’t need to be called again.

3.
In the scope of the view() function, the cls variable is the View class (eg DetailView, ListView, or whatever child of View is calling the function). Refering to the first argument of a class method as cls is a coding style specification from PEP8. It’s similar to the way we refer to the first argument of am instance method as self. So

self = cls(**initkwargs)

is basically the same as

self = View(**initkwargs) or self = DetailView(**initkwargs)

(depending on which class is inheriting this function).

This is, as you say, instantiating a new instance of the class. Up to this point, a View object has yet to be instantiated.

4.
Lastly the initkwargs are used when an instance of the class is created. It’s really as simple as adding each key, value pair as attributes of the new view object –

for key, value in kwargs.iteritems():
    setattr(self, key, value)

Leave a comment