Django Template Layer

Introduction

  • Writing Python code and designing HTML are two different disciplines. It’s much cleaner and more maintainable to separate the design of the page from the Python code itself.
  • If a view describes what data is displayed on a given page, the template describes how that data looks.

Template System Basics

  • A Django template is a string of text that is intended to separate the presentation of a document from its data.
  • Any text surrounded by a pair of braces is a variable.
  • Any text that’s surrounded by curly braces and percent signs is a template tag.
  • A filter is the most convenient way to alter the formatting of a variable

Example

<html>
<head><title>Ordering notice</title></head>
 
<body>
 
<h1>Ordering notice</h1>
 
<p>Dear {{ person_name }},</p>
 
<p>Thanks for placing an order from {{ company }}. It's scheduled to
ship on {{ ship_date|date:"F j, Y" }}.</p>
 
<p>Here are the items you've ordered:</p>
 
<ul>
{% for item in item_list %}
    <li>{{ item }}</li>
{% endfor %}
</ul>
 
{% if ordered_warranty %}
    <p>Your warranty information will be included in the packaging.</p>
{% else %}
    <p>You didn't order a warranty, so you're on your own when
    the products inevitably stop working.</p>
{% endif %}
 
<p>Sincerely,<br />{{ company }}</p>
 
</body>
</html>

Using the Template System

How to use a template system in Python code:

  1. Create a template object by providing the raw template code as a string.
  2. Call the render() method of the Template object with a set of variables.
>>> from django import template 
>>> t = template.Template('My name is {{ name }}.')
>>> c = template.Context({'name': 'Adrian'}) 
>>> print t.render(c)
My name is Adrian.
>>> c = template.Context({'name': 'Fred'})
>>> print t.render(c)
My name is Fred.

Template Inheritance

Template inheritance allows you to build a base "skeleton" template that contains all the common elements of your site and defines blocks that child templates can override.

One common way of using inheritance is a three-level approach:

  • Create a base.html template that holds the main look-and-feel of your site.
  • Create a base_SECTION.html template for each "section" of your site.
  • Create individual templates for each type of page.

This approach maximizes code reuse and makes it easy to add items to shared content areas, such as section-wide navigation.

Creating Template Objects

  • The Template class lives in the django.template module, and the constructor takes one argument, the raw template code.

Rendering a Template

  • Once you have a Template object, you can pass it data by giving it a context.
  • A context is simply a set of template variable names and their associated values. A template uses this to populate its variables and evaluate its tags.
  • A context is represented in Django by the Context class, which lives in the django.template module.
  • Its constructor takes one optional argument: a dictionary mapping variable names to variable values.

Multiple Contexts, Same Template

  • Once you have a Template object, you can render multiple contexts through it.
>>> from django.template import Template, Context
>>> t = Template('Hello, {{ name }}')
>>> print t.render(Context({'name': 'John'}))
Hello, John
>>> print t.render(Context({'name': 'Julie'}))
Hello, Julie
>>> print t.render(Context({'name': 'Pat'}))
Hello, Pa

Context Variable Lookup

  • The key to traversing complex data structures in Django templates is the dot character (.). Use a dot to access dictionary keys, attributes, methods, or indices of an object.
>>> from django.template import Template, Context
>>> person = {'name': 'Sally', 'age': '43'}
>>> t = Template('{{ person.name }} is {{ person.age }} years old.')
>>> c = Context({'person': person})
>>> t.render(c)
u'Sally is 43 years old.'

Method Call Behavior

  • If, during the method lookup, a method raises an exception, the exception will be propagated, unless the exception has an attribute silent_variable_failure whose value is True. If the exception does have a silent_variable_failure attribute, the variable will render as an empty string.
>>> t = Template("My name is {{ person.first_name }}.")
>>> class PersonClass3:
...     def first_name(self):
...         raise AssertionError, "foo"
>>> p = PersonClass3()
>>> t.render(Context({"person": p}))
Traceback (most recent call last):
...
AssertionError: foo
 
>>> class SilentAssertionError(AssertionError):
...     silent_variable_failure = True
>>> class PersonClass4:
...     def first_name(self):
...         raise SilentAssertionError
>>> p = PersonClass4()
>>> t.render(Context({"person": p}))
u'My name is .'
  • To prevent the template system of accessing alter methods the function attribute alter_data should be set.
def delete(self):
    # Delete the account
delete.alters_data = True

How Invalid Variables Are Handled

  • By default, if a variable doesn’t exist, the template system renders it as an empty string, failing silently.

Playing with Context Objects

  • Most of the time, you’ll instantiate Context objects by passing in a fully populated dictionary to Context(). But you can add and delete items from a Context object once it’s been instantiated.

Basic Template Tags and Filters

Tags

if/else

  • The {% if %} tag evaluates a variable, and if that variable is “True” (i.e., it exists, is not empty, and is not a false Boolean value), the system will display everything between {% if %} and {% endif %}.
{% if today_is_weekend %}
    <p>Welcome to the weekend!</p>
{% else %}
    <p>Get back to work.</p>
{% endif %}
  • The use of parentheses for controlling order of operations is not supported.

for

  • The {% for %} tag allows you to loop over each item in a sequence.
  • Each time through the loop, the template system will render everything between {% for %} and {% endfor %}.
  • The for tag supports an optional {% empty %} clause that lets you define what to output if the list is empty.
{% for athlete in athlete_list %}
    <p>{{ athlete.name }}</p>
{% empty %}
    <p>There are no athletes. Only computer programmers.</p>
{% endfor %}
  • There is no support for “breaking out” of a loop before the loop is finished.
  • Similarly, there is no support for a “continue” statement.
  • Within each {% for %} loop, you get access to a template variable called forloop. This variable has a few attributes that give you information about the progress of the loop:
    • forloop.counter is always set to an integer representing the number of times the loop has been entered. This is one-indexed, so the first time through the loop, forloop.counter will be set to 1.
    • forloop.counter0 is like forloop.counter, except it’s zero-indexed. Its value will be set to 0 the first time through the loop.
    • forloop.revcounter is always set to an integer representing the number of remaining items in the loop. The first time through the loop, forloop.revcounter will be set to the total number of items in the sequence you’re traversing. The last time through the loop, forloop.revcounter will be set to 1.
    • forloop.first is a Boolean value set to True if this is the first time through the loop.
    • forloop.last is a Boolean value set to True if this is the last time through the loop.
    • forloop.parentloop is a reference to the forloop object for the parent loop, in case of nested loops.

ifequal/ifnotequal

  • Compare two values and display something if they’re equal.
  • Only template variables, strings, integers, and decimal numbers are allowed as arguments to {% ifequal %}.

Comments

  • Just as in HTML or Python, the Django template language allows for comments. To designate a comment, use {# #}.

Filters

  • Template filters are simple ways of altering the value of variables before they’re displayed.

Example: This displays the value of the name variable after being filtered through the lower filter, which converts text to lowercase.

{{ name|lower }}

Using Templates in Views

Template Loading

  • Django provides a convenient and powerful API for loading templates from the filesystem.
  • In order to use this template-loading API, first you’ll need to tell the framework where you store your templates.
  • The place is in settings.py file, the ROOT_URLCONF setting.

Example: we’re using the function django.template.loader.get_template() rather than loading the template from the filesystem manually.

from django.template.loader import get_template
from django.template import Context
from django.http import HttpResponse
import datetime
 
def current_datetime(request):
    now = datetime.datetime.now()
    t = get_template('current_datetime.html')
    html = t.render(Context({'current_date': now}))
    return HttpResponse(html)

render_to_response()

  • Shortcut function.
  • The first argument to render_to_response() is the name of the template to use. The second argument, if given, should be a dictionary to use in creating a Context for that template. If you don’t provide a second argument, render_to_response() will use an empty dictionary.

Example

from django.shortcuts import render_to_response
import datetime
 
def current_datetime(request):
    now = datetime.datetime.now()
    return render_to_response('current_datetime.html', {'current_date': now})

locals()

  • It returns a dictionary mapping all local variable names to their values, where “local” means all variables that have been defined within the current scope.

Example

def current_datetime(request):
    current_date = datetime.datetime.now()
    return render_to_response('current_datetime.html', locals())

The include Template Tag

  • This tag allows you to include the contents of another template. The argument to the tag should be the name of the template to include, and the template name can be either a variable or a hard-coded (quoted) string, in either single or double quotes.

Template Inheritance

  • Template inheritance lets you build a base “skeleton” template that contains all the common parts of your site and defines “blocks” that child templates can override.
  • The first step is to define a base template — a skeleton of your page that child templates will later fill in.

Example: The {% block %} tags tells the template engine that a child template may override those portions of the template.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="en">
<head>
    <title>{% block title %}{% endblock %}</title>
</head>
<body>
    <h1>My helpful timestamp site</h1>
    {% block content %}{% endblock %}
    {% block footer %}
    <hr>
    <p>Thanks for visiting my site.</p>
    {% endblock %}
</body>
</html>

Example: A child template could be the following:

{% extends "base.html" %}
 
{% block title %}The current time{% endblock %}
 
{% block content %}
<p>It is now {{ current_date }}.</p>
{% endblock %}

One common way of using inheritance is the following three-level approach:

  1. Create a base.html template that holds the main look and feel of your site.
  2. Create a base_SECTION.html template for each “section” of your site. These templates extend base.html and include section-specific styles/design.
  3. Create individual templates for each type of page, such as a forum page or a photo gallery. These templates extend the appropriate section template.
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-Share Alike 2.5 License.