Main Content

Nesting Templates in Django

Archive - Originally posted on "The Horse's Mouth" - 2012-03-02 18:09:13 - Graham Ellis

Django's templates are HTML files into which your controller will fill web page content. This is done by means of an extra tagging language, which includes two groups of constructs:

a) construct starting with {{ and ending with }}, which are filled in with the value held in a field in the Context object.

Example:
  Copyright {{copyright}} in year {{year}}

and

b) formatting controls - keyword based commands starting with {% and ending with %}. There are a limited number (about 20) such commands.

Example:
  {% for colleague in clist %}
    &bull; How about asking {{colleague.0}}<br />
  {% endfor %}


Now in most applications you'll want all the pages to have a similar look and feel, with changing data. But they're unlikely to be so much the same that a single template will cover all of your needs. Take, for example, a system which displays data either in the form of summary list of all records, or it displays the full data for a single record. That's where nested templates are useful.

1. You create a template which covers all the parts of the page common to all (in our example, both types of) pages. And in that template, you place named blocks:

  <html>
  <head>
  <title>Staff Stuff</title>
  </head>
  <body bgcolor=#FFEEDD><h1>Staff Information
  {% block pagetitle %} Page Name {% endblock %}</h1>
  {% block tagline %} What this is {% endblock %}<br />
  {% block mainsection %} The Real McCoy {% endblock %}
  <hr />
  Copyright {{copyright}} in year {{year}}
  </body>
  </html>


The block names are your choice of word; the text within the block is a default value (great for debugging) which is displayed only if there is no available block of this name in the calling template file. Now - save that template file in a file which is not referenced in any way in the view controller Python - the link will come in a minute.

2. Create another template for the first of your page types - here's the index page template for my example:

  {% extends "staff/mybasepage.html" %}
  {% block pagetitle %}Index{% endblock %}
  {% block tagline %}Here are the various Roles, matey!{% endblock %}
  {% block mainsection %}{{mainbody|safe}}{% endblock %}


You'll note that it's in this file that we reference the overall template shown above, which we had chosen to call mybasepage.html

Create a second template - for the second type of page - here's the template page for each single record:

  {% extends "staff/mybasepage.html" %}
  {% block pagetitle %}[{{role}}]{% endblock %}
  {% block tagline %}Here are you colleagues in that area{% endblock %}
  {% block mainsection %}
  {% for colleague in clist %}
    &bull; How about asking {{colleague.0}}<br />
  {% endfor %}
  <hr />Please select <a href=index.html>EAR</a> for the Eindex
  {% endblock %}


You'll now find that when you render your page in the view controller, passing in your Context object, that the page you call up will load the base page from which it extends. Very near, and avoid the need for repeating yourself; Python's "DRY" philosophy extended to Django.

I have just finished a Python with Django course in Dublin and I'm awaiting my flight at the airport on my way home. We run public Python courses at our UK training centre (we have one starting on Monday!), and private Python courses onsite anywhere in Europe.

If you're looking to learn about the Django web framework, we don't run Public Django Training Courses, but with prior notice we can add an extra day onto the end of our public Python course, or include coverage within private course as we have done this week. Please get in touch!

P.S. We have lots more resources on Django ;-) including a complete set of files showing the above code and changes in context [here] on our web site.