In the first section of this chapter, we created a very simple view for our application's main page. We had to embed the HTML code of the page into the view's code. This approach has many disadvantages even for a basic view:
Good software engineering practices always emphasize the separation between UI and business logic, because it enhances reusability. However, embedding HTML within Python code clearly violates this rule.
Editing HTML embedded within Python requires Python knowledge, but this is impractical for many development teams whose web designers do not know Python.
Handling HTML code within Python code is a tedious and error-prone task. For example, quotation marks in HTML may need to be escaped in Python string literals, and the overall result may be unclean and unreadable code.
Therefore, we'd better separate Django views from HTML code generation before continuing with our application. Fortunately for us, Django provides a component that facilitates this task; it is called the template system.
The idea of this system is simple, instead of embedding HTML code in the view, you store it in a separate file called a template. This template may contain placeholders for dynamic sections that are generated in the view. When generating a page, the view loads the template and passes dynamic values to it. In turn, the template replaces the placeholders with these values and generates the page.
To help you better understand the concept, let's apply it to our main_page view. First of all, to keep our directory structure clean, we will create a separate folder called templates in our project folder. Next, we need to inform Django of our newly-created templates folder. So, open settings.py, look for the TEMPLATE_DIRS variable, and add the absolute path of your templates folder to it. If you don't want to hard-code the path into settings.py, you can use the following little snippet that will also work:
The structure of the template is very similar to the HTML code that we embedded in the main_page view. There is one small difference however; we used a special syntax to indicate sections that we wanted to change in the view. For example, {{head_title}} indicates a variable called head_title that can be changed inside the view. Template variables are always surrounded by double braces.
Now, let's see how to use this template in the view. Edit bookmarks/views.py and replace its contents with the following code:
from django.http import HttpResponse
from django.template import Context
from django.template.loader import get_template
def main_page(request):
template = get_template('main_page.html')
variables = Context({
'head_title': 'Django Bookmarks',
'page_title': 'Welcome to Django Bookmarks',
'page_body': 'Where you can store and share bookmarks!'
})
output = template.render(variables)
return HttpResponse(output)
As usual, we will go through the code line by line:
To load a template, we used the get_template method, which is found in the django.template.loader module. This method takes the filename of a template and returns a template object.
To set variable values in the template, we created an object called variables of type Context. The constructor for this type takes a Python dictionary whose keys are variable names (without double braces), and whose values are the values of these variables.
To replace template variables and create HTML output from the template, we used the render method. This method takes a Context object as a parameter, so here we pass the variables object to it.
Finally, we returned the HTML output wrapped in an HttpResponse object.
As you can see, the benefits of this approach over the old one are clear. We no longer have to deal with HTML within Python. Putting the HTML code into its own file is a lot cleaner. In addition, the template system provided by Django makes template management an easy and straightforward task.
The template system offers a lot in addition to variable substitution. It provides conditional statements to test whether a variable is empty or not, and a 'for' loop to iterate through a list and print its items, among many other features. We will see how to employ some of these features in the next section, in which we will use all the knowledge that we have learned previously to create user pages.