Working with template language
A common requirement when creating web applications is the need to add dynamic data inside HTML markup. This data can be represented by a variable containing dynamic or calculated values or values stored in the database of the application.
Either way, a web framework needs a way to understand this data. To address this, Django uses Django template language or DTL to separate the presentation and application logic.
As you learned earlier, a Django template is a Python string or text document marked up using Django template language and interpreted by the template engine.
The DTL is based on the popular Jinja2 template engine, and has most of the features common to it. As a developer, writing code in a familiar language is beneficial.
DTL helps remove that barrier by providing flexibility that aligns with the core time-saving principle in Django of do not repeat yourself or DRY.
It also adds a layer of security as the Python interpreter does not execute the template code.
Once you understand the use of template languages, much of the logic in creating the templates becomes evident.
There are four main constructs in the syntax of DTL. They are:
- variables
- tags
- filters
- comments
Combined, they provide the substitute for basic functionalities present in a programming language.
Variables
Variables are surrounded by double curly braces. When the template engine encounters a variable, it evaluates that variable and replaces it with the result.
Variables return a dictionary-like object that maps keys to values.
{restaurant_name : 'Little Lemon'}
In this example, restaurant name is the key with the value of Little Lemon. When rendered, this template code displays Welcome to Little Lemon restaurant.
Similarly, you can use dictionary, attribute, and list index lookup using dot notation.
{{ my_dict.key }}
{{ my_object.attribute }}
{{ my_list.0 }}
Tags
Tags are the source of logic that you can add to templates. Tags are created using curly braces and the percentage symbol. {% variable %}
The most commonly used tags are the control structures such as if
and for
loops.
The if tag is used inside the template to render different outputs. A typical use case is to check the login status of a user.
The code in this example checks if the value of the Boolean variable logged in is true or false. If true, the page renders the welcome statement. If false, it renders the login link.
Another standard workflow is to iterate over the dictionary to display an unordered list. To do this using a template, you need to have some way of looping over the data and printing out the HTML markup with the data object for each item in the list.
For example, suppose you have a simple list that contains menu items for the restaurant. Each item has a name and a price. To create this menu statically, you wrap each menu item in an unordered list using the list item tag.
To create this Menu dynamically with templates, you add the for loop code where items repeat.
In this menu example, it’s inside the unordered list. The code will iterate over the menu list object and display the name and price. The variable item will keep a reference to each object as the iteration continues to go through each menu item.
Apart from if and for, there are many other texts such as extends and include, and you will learn about them later in this lesson.
Filters
Unlike tags, filters can change the values of the variables.
{{ variable|filter }}
For example, if you add a filter such as string upper, it will take an input string and convert it to uppercase.
{{string|upper}}
Filters can also additionally take an argument like when using the date filter.
{{ todays_date|date:"Y-m-d" }}
For example, you can pass the argument for year, month, and day, which produces a date in this exact format.
Comments
You can create comments using the curly brace and percentage symbols. Django ignores everything in-between the two tags.
It’s important to note that developers use comments for documentation as they do not render.
Template Language and Variable Interpolation
In this reading, you will further explore the templating language and how it can be used to create markup.
This reading will also showcase the use of variables and how they can be dynamically passed in a template to render out different content.
Introduce learners to the template language with variables, filters and tags.”
Template Engine
Modern web frameworks use a web template system to merge a data source with static HTML to generate dynamic web pages.
A web template is an otherwise static HTML script interspersed with placeholder blocks of template language code. The template engine takes one set of data from any source, such as a database table, substitutes in placeholders and renders the generated content to the client browser.
Django’s template engine uses its own Django Template Language. The default project template is configured that way. However, you may choose to use any other template language such as jinja2.
Django Template Language has three important components: variables, tags, and filters.
Template variable
As you have previously learned, templates are HTML pages. The DIRS
attribute of the TEMPLATES
variable in the settings.py
file points to the folder in which the templates are stored. Generally, the templates folder is in the root project folder.
The easiest way to display a template web page is by calling the render()
function from within a view function. Its three parameters are the HTTP request object, the page itself, and a context dictionary.
Assuming that the client URL is http://localhost:8000/myapp/Novak
, the following view function receives the path parameter from the URL dispatcher and passes it as context to the template:
The keys in the context dictionary are available to the template as a variable.
When put inside double curly brackets, the value is substituted at runtime.
Put the following statement in the body of index.html
.
As a result, if the view receives Novak as the parameter, Hello Novak
is rendered.
The value of any key in the context may be a singular object (string, integer), a list or a dictionary.
A certain view passes a ‘person’ dictionary as a context.
Inside the template, you can access the value associated with each key with the dot ("."
) operator just as the attributes of an object are used. For example:
This will render the following output on the browser.
- Name: Roger
- Profession: Teacher
Template tags
Just as there are HTML tags, the Django template language defines several tags. You can think of the tags as the keywords in a traditional programming language. You place the tags inside {% tag %}
symbols.
The if
and for
tags are important because they add processing logic to the web page.
{% if %}
With the if
tag, the template variable is checked against a Boolean expression and a block of HTML is rendered conditionally.
Even though the syntax of if
(and for
) is very similar to Python, Django template language (DTL) doesn’t use uniformly indented blocks. Hence, for every if
tag, there is an endif
tag.
A simple example of Django’s if
tag is as follows:
The following view passes {'user':'admin'}
dictionary as context to the template.
The conditional block in the template should be as follows:
{% for %}
You can construct a looping construct inside the template with {% for %}
and {% endfor %}
tags. It is used to traverse any Python iterable such as a list, tuple or string.
In the following example, you pass a list to the template as its context.
Inside the template, the for loop is constructed, much like in Python to render the names of languages as unordered list.
If the value of a context variable is a dictionary, you can traverse the key–value pairs using the for syntax.
DTL has a number of helper variables to be used within the loop:
forloop.counter
: The current iteration of the loop
Output:
List of Languages
- 1: Python
- 2: Java
- 3: PHP
- 4: Ruby
- 5: Rust
forloop.revcounter
: The number of iterations from the end of the loop (1-indexed)
Output:
List of Languages
- 5: Python
- 4: Java
- 3: PHP
- 2: Ruby
- 1: Rust
forloop.first
: True if this is the first time through the loop
Output:
List of Languages
- True: Python
- False: Java
- False: PHP
- False: Ruby
- False: Rust
forloop.last
: True if this is the last time through the loop
Output:
List of Languages
- False: Python
- False: Java
- False: PHP
- False: Ruby
- True: Rust
forloop.parentloop
: For nested loops, this is the loop surrounding the current one.
If you pass the following dictionary object as context:
The template has nested loops as follows:
Output:
1:digits
One
Two
Three
2:tens
Ten
Twenty
Thirty
{% comment %}
Everything between {% comment %}
and {% endcomment %}
is ignored. An optional note may be inserted in the first tag.
{% block %}
Defines a block that can be overridden by child templates. This tag will be discussed when you learn about template inheritance.
{% csrf_token %}
This tag is used in a form template as protection to prevent Cross Site Request Forgeries (CSRF). This tag generates a token on the server-side to make sure to cross-check that the incoming requests do not contain the token. If found, they are not executed.
{% include }%
Loads a template and renders it with the current context. This is a way of “including” other templates within a template. The template name can either be a variable or a hard-coded (quoted) string, in either single or double quotes.
{% with %}
This tag sets a local variable that is available between {% with %}
and {% endwidth %}
tags.
Filters
The filters modify the representation of the variable used in the template code. The modified value of the variable is rendered in the {{ }}
tags. The filter is applied with the | (known as Pipe) symbol. The general form of using filter is:
DTL has defined a number of filters. Here are some of the most frequently used:
default
Django view passes a variable to the template. In the code below, value
is a template variable. If it has been initialized in the view, it is set to the specified default, which in this case is nothing
.
If the value is an empty string, the output will be nothing.
join
This tag is similar to Python’s str.join(list)
method. It joins the items in a list with the given separator.
For example:
If the view passes a list [' Django ', 'Template', 'Language']
, the output will be the string "'Django_ Template_Language'"
.
length
When applied, this filter returns the length of the sequence received from the context. This works for both strings and lists.
If name
is "John"
, the output will be 4
. It returns 0 for an undefined variable.
first
Returns the first item in a list. Assuming that the list from the view function is ['a', 'b', 'c']
.
The output will be 'a'
.
last
If value is the list ['a', 'b', 'c', 'd']
, the output will be the string "d"
.
lower
Converts a string into all lowercase.
upper
upper
converts a string into all uppercase.
title
title
converts a string into title case by making words start with an uppercase character and the remaining characters lowercase.
For example:
string = "django template language"
, the output will be "Django Template Language"
.
length
Returns the length of string or a list.
For the above string variable, the output will be 21
.
wordcount
wordcount
works on a string variable only and returns the number of words. For the above string variable, the output will be 3
.
In this reading, you explored the elements of Django Template Language, variables, tags and filters.
Dynamic Templates in Django
In the project directory, make a templates
folder, and make a menu.hml
inside.
To make sure that django finds the templates, you should add the templates folder name in the settings.py
TEMPLATES list. 'DIRS':['templates']
NOTE
In these examples I demonstrated the rendering of dynamic data using a dictionary as the data source. It’s important to know that this data source can be other things like a database or an API.
Mapping model objects to a template
One of the reasons Django is so popular is that it allows developers to create dynamic website content quickly. With just a few steps, you can take data that’s stored in a database, write some logic for it, and then display it to the end user in the browser.
If open Django administration in the browser, recall that this model contains data like the menu items for hummus, falafel and so on.
Template inheritance
When developing web applications. In Django recall the key principle of don’t repeat yourself are dry duplication whether inadvertently or purposeful can lead to maintenance issues and logical contradictions.
TIP
Every distinct concept or piece of data should live in one and only one place. The framework within reason should deduce as much as possible from as little as possible.
For example, to create the same header and footer sections across multiple pages for the little Lemon website you can make a copy of the markup and save it multiple times. Then only change the corresponding title for each web page.
But a more efficient method is to build a base template containing all the common elements of the website and assigned them to a block. This block can then be repeated on every web page.
Suppose you have the task of creating a prototype for the new Little Lemon website. The website has four pages for home about Menu and book.
So far only one prototype page exists and this is for the about us page. In order to work with templates efficiently, it helps to break the page up into sections and in Django these sections are referred to as blocks.
Header
For example, at the very top of most websites you find what is called the header and this is the first section or block. The header often contains the company name and logo. It also usually has links to the different pages of the website which is known as the navigation menu.
Additionally, the header might contain a section where users can log in. This usually includes a user icon along with the drop down menu with a link to the user profile.
TIP
When working with the page layout, it’s best practice to keep the look of the header consistent and in the same position across all the pages of a website. This consistency is essential for a good user interface and contributes to a positive user experience.
Because if the header is visible on all pages of your website, it makes it faster and easier for the user to navigate.
Footer
The same can be said for the footer. The footer is a section at the bottom of a web page that contains essential company or contact details, navigation links and copyright information.
At this point, you may be wondering how do I incorporate the header and footer across the four pages for the little lemon website, that’s where you use template inheritance.
Template inheritance
Template inheritance allows you to split out content by breaking it down into individual components. You can then insert and reuse these components without duplicating work.
Include Tag
The html markup on the base page now references the files containing the code for the header and footer sections, using the include tag. If you need to make an update to either of these files, you’ll only need to do it once and not on every page.
The include tag lets you either specify a template string or a variable to allow conditions for different rendering.
For example, say you want to pass an object which contains information such as the page name. To do this, you can pass a dictionary as an argument inside the render function to pass variables or objects to the template.
To gain access to specific data from the header file such as the page object, you need to add additional attributes inside the include tag.
Once added, you can access the page object anywhere on the page; For example, to display the page name as a heading element.
NOTE
It’s important to remember that this object is part of the dictionary that was passed inside the render function inside the view.
When using the include tag, you instruct the page to render this sub template and include the html. This means that there is no shared state between included templates. Each include is an independent rendering process.
Extend Tag
This is similar to the include tag with syntax and usage. However, its purpose and functionality differ.
Extend
Extend allows you to replace blocks or content from a parent template, as opposed to include that will include parts. Extend creates a parent child relationship where parents functionality can be overwritten. Include, on the other hand, simply includes rendering a template in the current context.
There are two ways to use the extends tag.
- The first is that it can use the string literal as the name of the parent template to be extended.
{% extends "base.html" %}
- The second is it can make use of the value of a variable. Once the variable evaluates to a string, Django will use that string as the name of the parent template.
{% extends variable %}
For example, say you have a file called header.html
, that contains code for a navigation menu represented as an unordered list.
You can extend the file contents of header.html
to a file called about.html
.
The code will effectively add the contents of header.html
to the content inside about.html
.
More on Template inheritance
This reading introduces template inheritance, along with its main features.
You will learn how template inheritance can be used inside a standard HTML page and how child templates can override blocks inside it. Additionally, you will explore the concept of static files in Django.
Inheritance in Django Template Language
The term inheritance is associated with the principle of object-oriented programming. It refers to the mechanism of a child class inheriting the properties of its parent class, and if required, extending or overriding them.
The question is how is the term inheritance used in relation to the template language?
There are many view functions defined in a Django application. Each view renders a different template (or the same with a different context). Ideally, you want all the web pages to look consistent. For example, elements such as the header, footer, and the navigation bar, must appear similar across all pages.
Structure of parent template
Let us assume that you’re building a three-page web application with a home page, a registration page, and another for logging into the application. Each page should have a main header, a footer, and a sidebar with links to the pages. The corresponding content of each page should appear to the right of the sidebar and between the header and footer.
{% block %} tag
Template inheritance helps to implement this structure and it’s similar to the one in object-oriented programming. It is a very powerful, yet equally complex feature of Django Template Language. Template inheritance is implemented with the {% block %}
and {% endblock %}
tags.
The block is identified by the given name to be overridden in the child template.
First, identify the components that are required because these will be used across all the web pages. Include those that show variable content on each page. Use the block tags to mark the code blocks with variable content as a dummy block or with no contents.
Base template
For the above skeletal structure, the header is represented by the following HTML:
The middle part of the page has two sections, represented in two <div>
tags of 20% and 80% width. The one on the left is a sidebar.
For now, let us add dummy links to the menu items.
The remaining part of the page is where the contents of each page will be displayed. Once again, mark this as a dummy block with no text between the block tags.
Now, address the footer of the page.
Put the above code blocks in a base.html
file and save it in the templates
folder. Note that this file will never be rendered as is but the templates for home, register, and login views will inherit it.
Add views
Now, add the view functions for the three operations planned for the applications. Open the views.py
file and add the following code:
You also need to update the URL pattern of the app.
Next, replace the dummy hyperlinks in the sidebar with the URLs registered above.
Child templates
Writing the templates for the views is straightforward because the structure is already defined in the base.html
. The {% extends %} tag imports the base template components in the child template. Create a new file named home.html
in the templates
folder and add the following line.
We intend to keep the same header, the sidebar, and the footer defined in the base template and put the relevant code inside the contents
block. Now, add the following lines in home.html
and save it.
At this stage, start the server and visit /myapp/home/
URL. Since this path is mapped to the home()
view, you should get the following page:
Similarly, create register.html
and put it in the templates folder.
The /myapp/register/
URL invokes the register()
function. It renders the registration page as below:
Before creating the login page, let us make some changes to the base template. You’ll want the login page to display some additional text in the footer. For that, the footer is placed in the block tag. Open the base.html
and change the footer to:
Now, save the login.html
template with the following code:
Notice that the {{ block.super }}
tag has been used. It is similar to Python’s super()
function whereby you access the parent class methods in a child class. In the same way, the contents of the footer block will be rendered on the login page. Now, include additional text in the block as a part of the header, for the login page.
So, we have a “base.html
” and three child templates – “home.html
”, “register.html
” and “login.html
” - in the templates folder.
The /myapp/login/
URL displays the following output with the modified footer.
Static files
In addition to the dynamic content, a web application needs to serve certain static content to the client. It may be in the form of images, JavaScript code, or style sheets. Django’s default project template includes django.contrib.staticfiles
in INSTALLED_APPS
.
The project’s settings file (settings.py
) has a static_url
property set to 'static/'
. All the static assets must be placed in the myapp/static/myapp
folder as the static_url
refers to it.
While rendering an image from this static folder, load it with the {% static %}
tag. HTML provides the <imgsrc>
tag. Instead of giving the physical URL of the image to be rendered, use the path that is relative to the defined static_URL
.
In this reading, you learned how to use the template inheritance technique to build multiple templates with a consistent layout. You were also introduced to the mechanism of serving static assets.
Working with Template inheritance
Remember, the Extends tag allows you to replace blocks or content from a parent template. It creates a parent-child relationship where the child can overwrite the parent functionality.
Likewise, the Include tag adds parts and includes the rendering of a template in the current content.
It is easy to get confused between Extends and Include, but there are differences that will become clearer with practice.
Suppose that you must design the Little Lemon website that contains three pages called Home, Menu and about. While the contents of each of these pages will differ, there are a few basic styling components that need to be uniform across the website.
Additionally, you may want the menu bar as part of the header so that it can be present on all pages.
These are the three pages you are creating for the Little Lemon website. Ensure that you update your URL configuration file both at the project and app levels. Also, map the respective URLs to the views.
Next, update the settings.py file by adding the app inside installed apps. Then create a template folder as part of DIRS in Templates. To work with templates, you need to create a folder called templates
by right clicking on the My Project folder and selecting New folder.
When working with template inheritance, you need to create another folder in My project called partials
. This is where you will include the header information.
Now let’s continue by creating a base HTML file inside the Templates folder, which will contain the code for the base HTML that you want inside all other pages of the website.
Still inside the Partials folder, create the three pages for the Little Lemon website about, index and menu.
Also, create a file called _header.html
in the Partial folder.
This is a file that you will use inside the Include tag in the base HTML file.
Now that you have the file structure set up, let’s begin by adding some code to the base HTML file. Remember that you can just type Exclamation Mark and press Enter to add the basic HTML stub.
base.html
:
index.html
:
menu.html
:
about.html
:
Remember, you did not add any specifications for a background color in the index file. What happens here is that the background that you specified in your base HTML file is extended from the base HTML file.
Now let’s add header information using the Include tag, you need to add content to the header file and save it.
_header.html
:
To carry this through consistently to all the Web pages, go to the base dot HTML file and add an Include tag that contains the header file reference.
base.html
:
PythonDjangoHTMLTemplateFront-end
Previous one → 12.Templates | Next one → 14.Debugging and testing