Using Templates

Templates play a very important role in the Django framework model. It is the templates that allow developers to separate application logic from presentation. Again, models define data structures, view functions are responsible for data queries and filtering, and finally templates define how data is represented to the end user.

Django comes with a very flexible and sophisticated template language. Let's look at how to use templates with the data obtained by the view functions. First we need to define a view that will query the database and get the information we will then present to the users. Listing 3-8 shows the new display function.

Listing 3-8. A view function that uses a template to present data def display(request, address=None): if not address:

parent = None else:

parent = NetworkAddress.objects.get(address=ip, network_size=int(net_size)) addr_list = NetworkAddress.objects.filter(parent=parent) return render_to_response('display.html',

As you already know, Django's URL dispatcher calls the display function with either no initial IP address (when users request top-of-the-tree listing) or the initial IP address (a request to display the contents of a subnet). If the address field is empty we will display all tree nodes that have no parents. If the address field is not empty, we need to get the list of tree nodes that have a parent set to the given address. The results are stored in addr_list and are passed to the template.

There are two entities that need to be displayed: information about the current tree node and a list of its children. So we have to pass both as variables to the template rendering procedure. In the example we use a shortcut function called render_to_response, which accepts two parameters: the name of the template file and a dictionary of variables the template will use to render HTML output. You can import the render_to_response shortcut with the following import statement:

from django.shortcuts import render_to_response

As you can see, we specify the template name without any preceding directory paths, so how does Django know where to look for the template? By default the following template loaders are enabled in the settings. py configuration file:

TEMPLATE_LOADERS = (

'django.template.loaders.filesystem.load_template_source', 'django.template.loaders.app_directories.load_template_source',

We are using the functionality provided by the app_directories loader. This loader looks for templates stored in the application directory under templates/ subdirectory. Storing templates with the application is extremely useful, because this allows developers to distribute a set of default templates with each application. So going back to our example, we need to create a subdirectory called templates in the application directory ip_addresses. We then create the template shown in Listing 39, which takes care of displaying information passed to it by the display view function.

Listing 3-9. A template for the display view {% if parent %}

<h1>Current address: {{ parent.address }}/{{ parent.network_size }}</h1> <h2><a href="../../{% if parent.parent %}{{ parent.parent.address }}/{{w parent.parent.network_size }}/{% endif %}">Go back</a></h2> {% else %}

<h1>At the top of the networks tree</h1> {% endif %}

{% for address in addresses_list %}

<li><a href="{% if parent %}../../{% endif %}{{ address.address }}/{{-<

address.network_size }}{% ifequal address.network_size 32 %}/modify/{% endifequal %}">{{-

address.address }}/{{ address.network_size }} </a>

{% ifequal address.network_size 32 %}(host){% else %}(network){% endifequal %}

{{ address.description }}

{{ address.address }}/{{ address.network_size }}/delete/">delete</a> |

{{ address.address }}/{{ address.network_size }}/modify/">modify</a>) </li> {% endfor %} </ul> {% else %}

{% ifequal parent.network_size 32 %} This is a node IP

No addresses or subnets in this range {% endifequal %} {% endif %}

<h2><a href="add/">Add new subnet or node IP</a></h2>

You might have already guessed that template language tokens are surrounded by {% ... %} or {{ ... }}. The difference between these two is that the former is used to surround command and process control statements, such as comparison and validation operators, while the latter is used to indicate that the contents of a variable need to be displayed at the specified location. All variables follow the same Python convention when referencing object properties. For example, in the template parent is an instance of the NetworkAddress model class, and as such parent has the property address. To display that variable in the template, we need to reference it as parent. address.

Table 3-4 lists the basic command structures that you are going to find yourself using quite often.

Table 3-4. The Most Common Elements of the Django TemplatingLanguage

Structure Description

Most commonly used to test whether the variable is defined and the contents are not empty. Depending on the result, you can either display the value of the variable or provide an informational message advising that the value is not found.

Loops through all items in <list> and assigns individual list items to <variable>, which you can use in a for construct.

Compares two variables <variable1> and <variable2> and processes one of the two template blocks depending on the result.

Everything between these two operators is ignored. {% endcomment %}

As you can see from the template, I've already added URL links to delete, modify and add records. All that is possible even at this stage, simply because we initially set the requirements and at any stage of the development process we precisely know what needs to be done. In this instance, the application is not ready yet to perform these actions, but we need to do the layout design and implement that within the template. This is especially useful if you need to hand over the template to somebody else, as they wouldn't have to guess what actions and what links you might require and create them even if the functionality has yet to be implemented.

Figure 3-4 shows how the application web page looks when you have navigated to one of the precreated network addresses.

{% for <variable> in <list> %} {% endfor %}

{% ifequal <variable1> <variable2> %} {% else %} {% endifequal %}

f ^ ^ http //www.example.com/ip_addresses/networkaddress/192.168.0.0/24/

I « _ | + l^hnp//www.example.coni/.p_addfesies/networkaddfe5S/192.168.0.0/24/ C flip;' /»«» rumplt comiip iddi

Current address: 192.168.0.0/24

Go back

• 192.168.0.0/25 (network) Subncl 1-1 (delete I modify)

• 192 168.0.128/25 (network) Subncl 1 -2 (delete I modify)

Addjiew subnel or node IP

Figure 3-4. A listing of the network addresses

Was this article helpful?

0 0

Post a comment