elcome to our second installment of the series. As we are not satisfied with our view merely stroking our ego we want to go a step further. After reading this post we want to be able to have our view stroke our ego with a nicely formatted (standards compliant) HTML-page, and possibly add some context to the whole thing. For this purpose we will progress a little further intodjango/views/generic/base.py and see what other classes we can find there.
Django provides us with three more classes we will take a look at right now (there’s a fourth one, a RedirectView, which we will pay no attention to for now):
Now, the nomenclature of these classes already suggests that there are different kinds of classes used in Django’s class based views. We have View classes, and Mixin classes. So let’s take a view at what methods these classes provide, to understand their purpose.
We start out with the very simple class ContextMixin:
class ContextMixin(object): """ A default context mixin that passes the keyword arguments received by get_context_data as the template context. """ def get_context_data(self, **kwargs): if 'view' not in kwargs: kwargs['view'] = self # add view instance to context return kwargs
class TemplateResponseMixin(object): template_name = None response_class = TemplateResponse # inherits from HttpResponse def render_to_response(self, context, **response_kwargs): return self.response_class( request = self.request, template = self.get_template_names(), context = context, **response_kwargs ) def get_template_names(self): if self.template_name is None: raise ImproperlyConfigured # this will scold us if we # forget to name a template else: return [self.template_name]
We observe, that the Mixin classes provide us with additional functionality on top of the basic handling of requests provided by the View class. The ContextMixin is responsible for preparing the context dictionary, whereas the TemplateResponseMixin provides us with an interface to template rendering as well as returning the appropriate HttpResponse object.
So let’s take a look at the TemplateViewClass and see how it works:
class TemplateView(TemplateResponseMixin, ContextMixin, View): def get(self, request, *args, **kwargs): context = self.get_context_data(**kwargs) # prepare context data return self.render_to_response(context) # return rendered http # response object.
With this knowledge, let’s put the TemplateView class to some use. Again, we start by inheriting our own personal view class from TemplateView (we could also call TemplateView.as_view() directly from urls.py with some configuration parameters):
# myapp/views.py class MyTemplateView(TemplateView): pass # myproject/urls.py from django.conf.urls import patterns, include, url from myapp.views importMyTemplateView urlpatterns = patterns('', url(r'^mytemplateview/', MyTemplateView.as_view(), name='mytemplateview'), )
<html> <head> <title>My Template View</title> </head> <body> <h1>My Template View</h1> <p>Hello Handsome!</p> </body> </html>
# myapp/views.py class MyTemplateView(TemplateView): template_name = "mytemplateview.html"
If we point our browser to /mytemplateview/ again we will be greeted by the familiar uplifting welcome, complimenting our looks. So now, let’s go and add some context to that. For this we simply override the get method of TemplateView (don’t forget to explicitly call the parents get method, though):
# myapp/views.py class MyTemplateView(TemplateView): template_name = "mytemplateview.html" def get(self, request, *args, **kwargs): kwargs['greeting'] = 'Bonjour' # add a keyword # and value to the context return super(MyTemplateView, self).get(request, # call get *args, # method of **kwargs) # TemplateView # class
<html> <head> <title>My Template View</title> </head> <body> <h1>My Template View</h1> <p>{{ greeting }} Handsome!</p> </body> </html>