Django Templates

This is my fourth article in the Django series. We are going to separate HTML code from python code by using Django templates and learn some more cool stuff about templates.

                     Django Templates 

This is the fourth article of the Django series. Last time we customized our welcome page but remember, we had to embed the HTML code of the page into the view's Python code. There are a few problems with this approach:
  • 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. (The scenario we discussed last time.)
 
Yeah, this could be you with HTML embedded in Python :D 
 
  • 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.

And as I said I won’t leave you alone in the mess so here I am. We’re going to separate our HTML code from Django views. Django provides a component that will help us accomplish this task; it is called the template system. Let’s apply it to our welcome page and see how it works.

First of all, create a separate folder called template in your project folder. This is just to keep our directory structure clean. A fun thing is if you’re using Pycharm then you can see this templates folder already created for you. It’s just not created but also its path is already added in settings.py. If you’re creating your own template folder then you need to inform Django about it. Open settings.py, look for the TEMPLATE_DIRS variable and add the absolute path of your template folder to it. Or if you don’t want to hard-code the path into settings.py then use the following code.

 
  1. import os.path  
  2. TEMPLATE_DIRS = (  
  3.    os.path.join(os.path.dirname(__file__), ‘templates’),  
  4. )  
What it simply does is that it informed Django where to look for the template. Now, let’s move to our HTML part. Create a file called index.html in the template folder and edit it with the following content:
 
  1. <!DOCTYPE html>  
  2. <html lang="en">  
  3.   
  4. <head>  
  5.     <meta charset="UTF-8">  
  6.     <title>Welcome Page</title>  
  7. </head>  
  8.   
  9. <body>  
  10.     <h2>Hello World</h2>  
  11.     <p>Welcome to my first Application in Django</p>  
  12. </body>  
  13.   
  14. </html>  
Pretty straightforward HTML code. All it does is display the same welcome message we did last time but this time without any Python code. Let’s see how to view this template in the view. Edit webapp/views.py file as follow:
 
  1. from django.shortcuts import render  
  2.  def main_page(request):  
  3. return render(None, 'index.html')  
That’s right. All we need is three lines of code. Let's break down the code.
  • We imported render method from django.shortcut.
  • We just defined the view using main_page as its name and passing request object to it.
  • In order to create HTML output from the template, we used the render method. It combines a given template with a given context dictionary and returns an HttpResponse object with that rendered text.

As per the documentation, render function is somewhat like this. 

  1. render(request, template_name, context=None, content_type=None, status=None, using=None)  
Required Arguments:

request:

The request object is used to generate this response. In our case, we are just displaying a static HTML page so we used request=None.

template_name:

The full name of a template to use or sequence of template names. If a sequence is given, the first template that exists will be used. We named our template as index.html so we used its name as an argument to our function.

Other arguments are all optional but let me explain them too.

Optional Arguments:

context:

A dictionary of values to add to the template context. By default, this is an empty dictionary. It means that it won’t make any difference if you call the function with an empty dictionary as render (None, 'index.html', {}) or without it. But if a value in the dictionary is callable, the view will call it just before rendering the template.

content_type:

The MIME type to use for the resulting document. Defaults to the value of the DEFAULT_CONTENT_TYPE setting.

status:

The status code for the response. Defaults to 200.

using:

The NAME of a template engine to use for loading the template.

Enough of the explanation. Now, run the server and you should see the exact screen you saw last time.

 

And Boom!

Now you have your HTML code separated from python. But that’s the static page. Is that all by Django? What if I want to integrate some variables on the page? Luckily! Django does support variable integration. Variables are surrounded by a pair of curly braces {{ }} like this. Let’s see how it works.

Open your index.html file and replace the code as follows:

 
  1. <!DOCTYPE html>  
  2. <html lang="en">  
  3.   
  4. <head>  
  5.     <title>{{ head_title }}</title>  
  6. </head>  
  7.   
  8. <body>  
  9.     <h1>{{ page_title }}</h1>  
  10.     <p>{{ page_body }}</p>  
  11. </body>  
  12.   
  13. </html>  
The structure of this template is very similar to the one before. Just a small difference, however; we used the special syntax for variable support to indicate the sections we want to change in our view.

Now, open views.py and edit its content as follow:

 
  1. from django.shortcuts import render  
  2. def main_page(request):  
  3. return render(None, 'index.html', {'head_title''Welcome Page',  
  4.                                    'page_title''Hello World',  
  5.                                    'page_body''Welcome to my first App in Django.'})  

We talked about the render’s optional argument context. In the above code, we just used that argument and loaded the page as per our context.

You can use it to pretty much display anything. For example,

  1. My first name is {{first_name}} and my last name is {{last_name}} 

With a context of {‘first_name’: ‘Mehreen’, ‘last_name’: ‘Tahir’}, this template renders to:

My first name is Mehreen and my last name is Tahir.

Template Tags and Filters

Django comes along the whole template system. The mains of this system are variables and tags. We have seen the variables so let’s talk about the Tags.

Tags

Tags provide arbitrary logic in the rendering process. They are surrounded by {% %} and can be used to output content or as a control structure. As

  1. {% if today_is_weekend %}  
  2.    <p>Welcome to the weekend!</p>  
  3.       {% else %}  
  4.    <p>Get back to work.</p>  
  5. {% endif %} 

Or,

  1. {% comment %}  
  2. This is a multi-line comment.  
  3. {% endcomment %} 
Or,
  1. {% block %}  
  2.    This block text can be overridden by child template. It is what we call template inheritance.  
  3. {% end block %}  

It could also be,

  1. {% csrf_token %}  

You’re going to use this special template tag when dealing with forms. It provides easy-to-use protection against Cross Site Request Forgeries.

Also,

  1. {%extends 'template name'%}  
  2. This tag is used to inherit from a base template. 

 

Filters

Filters are an effective way to modify the data before sending it to the template. Like this,

  1. {% filter lower %}  
  2.    This text will appear in all lowercase.  
  3. {% endfilter %} 
An upper filter can also be used,
  1. {% filter upper %}  
  2.    This text will appear in all uppercase.  
  3. {% endfilter %}  

There are a lot of cool filters like capfirst, pluralize, line breaks etc. or maybe use something like this.

  1. {{ value|add:"1" }}  
  2. If value is 2, then the output will be 3. 

This is just a glimpse of the powerful tag system of Django. Go ahead and feel free to experiment with it.

To Readers

If you get bored of the content then consider downloading the complete app sample from my GitHub profile and get your hands dirty right away. But if you want to understand Django more then wait for my next article :)