In my previous entry I showed a simple TemplateView example. I’ll make it even simpler. views.py:
from django.views.generic.base import TemplateView
class SomeView(TemplateView):
template_name = 'my_app/someview.html'
def get_context_data(self, **kwargs):
return {'name': 'reinout}
And in urls.py:
import ...
urlpatterns = patterns(
...
url(r'^class_based_view/$',
my_app.views.SomeView.as_view(),
name='class_based_view'),
As you can probably see, there are two things you need to somehow know when subclassing from TemplateView:
“You need to know something somehow” is perfectly fine: that’s what documentation is for. You need to know a lot of those things, like that models go into models.py and templates into a templates/ subdirectory, for instance.
For better understanding, let’s dive into the django code and take a detailed look at what happens. That way, we can better understand what happens and that way we can make our own view and perhaps our own mixins.
First things first: open django/views/generic/base.py. Or look at it online in a second tab.
View is the base class for all views. It takes care of two things that you should know about:
In your urls.py, you need to import the class and feed it to your urls with a .as_view() appended. You might ask why that .as_view() is needed. It is needed because you want your view objects to be thread-safe. That’s an expensive word for “self.bla_bla = 3 should be safe to use and self.bla_bla should not end up as a value in another view instance”. The way urls.py works (it expects callables) wouldn’t work nicely with classes. Anyway, that’s High Python magery. Nothing to worry about. Just accept that the .as_view() is a pretty fine and decent solution :-)
You can even pass keyword arguments to as_view() which will be set as attributes on your view objects. So YourView(template_name='my_view.html') will give your view a self.template_name with the value 'my_view.html'. Provided your view had some default value for that attribute, otherwise you’d get an error: nicely explicit.
Behind the scenes, what as_view() returns is the .dispatcher() method that basically just calls .get() for a GET request, .post() for a POST request and so on. Of course it passes along arguments and keyword arguments that your url config wishes to pass along.
Now, you don’t need to worry about that dispatch method. You won’t ever have to customize that one. Likewise the as_view method. Remember the two customization points:
Hey, our first mixin! Python support multiple inheritance. So your view can inherit from more than one class. This way, you can mix in one or two methods or attributes into your class by inheriting from an extra mixin class.
Warning: using mixins looks fine on the first sight, but experience has shown that debugging can quickly become an utter hell as you have to look in 10 different spots before you figure out which method does what to your hapless data... (8 years of zope/plone experience speaking here!)
Anyway... TemplateResponseMixin mixes in two really important things:
As it is a mixin, this render_to_response() isn’t actually called anywhere within the class itself. So onwards to...
... TemplateView inherits from both View and TemplateResponseMixin. It is indended just for rendering a template with a context. Technically, it means responding to a GET request and returning a response.
What you need to know about TemplateView itself:
So. TemplateView is useful by itself. For many views, this is what you ought to be subclassing. Despite the many layers and methods-calling-other-methods that happens, there are just two items you need to implement in your subclass:
Just for clarity, here’s the example view again:
from django.views.generic.base import TemplateView
class SomeView(TemplateView):
template_name = 'my_app/someview.html'
def get_context_data(self, **kwargs):
return {'name': 'reinout'}
In the end, the TemplateView class is pretty simple when you actually use it.
The underlying mechanism is relatively elaborate and depends quite a lot on every part doing exactly what it has to do. And it consists out of quite some parts. So I hope the complexity you can build into it doesn’t grow out of hand.
Getting the RequestContext automatically is a big plus for TemplateView.
Have fun writing class based views! I’ll probably write more about them in the weeks to come as I discover more things. There are handy views for redirecting, for handling forms and so on. Lots to discover.
My name is Reinout van Rees and I work a lot with Python (programming language) and Django (website framework). I live in The Netherlands and I'm happily married to Annie van Rees-Kooiman.
Most of my website content is in my weblog. You can keep up to date by subscribing to the automatic feeds (for instance with Google reader):