Contact Information

KodeBlog

We're Available 24/ 7. Drop us an email.

Django Templates

In the last tutorials, we have created a very simple page. We also created the models needed for our application and populated the database using the Admin panel. Now we are going to create pages that look like real applications. We will create templates for the application and add CSS and JS to it.

Topics to be covered

We will cover the following topics in this lesson

  • Templates
  • Template Configuration
  • Template Inheritance
  • Passing data to templates
  • Static Files
  • Project URLs
  • Lesson Challenge
  • Course Project Templates
  • Summary

Templates & Syntax

“A template contains the static parts of the desired HTML output as well as some special syntax describing how dynamic content will be inserted.” Django allows us to create templates based on each other. We can create blocks so we will be able to put content later dynamically. We can also pass objects to our templates, loop in them, show related objects, etc.

Django templates are saved as *.html files and a special syntax is used to identify Django template code that must be interpreted at runtime.

Django template uses a single curly bracket followed by a percentage symbol to create dynamica content like so

{% code goes here %}

For example, the following code makes a child template inherit from a parent

{% extends "base.html" %}

The following defines a content block

{% block content %}
 <h1>Welcome to our online bookstore</h1>
{% endblock %}

We will learn more about Django template tags as we proceed with the lesson.

Template Configuration

We need to create a templates directory in the root of our project. Open the directory bookstore then in it, create a new directory called templates.

Next, open the file settings.py and in the templates section, locate the following line

'DIRS': [],

Replace the above line with the following

'DIRS': [os.path.join(BASE_DIR, 'templates')],

HERE,

  • 'DIRS': [os.path.join(BASE_DIR, 'templates')], tells Django that the templates directory is located in the root project BASE_DIR in a directory called templates.

Our project is split into applications and each application will have its own template files. We need to configure Django so that it first looks into the templates directory in the respective application and if the template is not found, then look in the root templates directory.

The variable APP_DIRS should be set to TRUE as shown in the code below

'APP_DIRS': True,

Template Inheritance

Most applications or websites have elements that are common to all pages. For example, the website logo, header navigation menu, footer etc are the same on all pages but only the main body is what changes.

Template inheritance allows us to define all these common elements in a single page then we dynamically inject the unique section in it.

Let's look at a practicalexample.

Create a new file base.html in the directory /bookstore/templates

Add the following code to it

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
        <title>KodeBlog Online Bookstore</title>

        <!-- Bootstrap -->
        <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">

        <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
        <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
        <!--[if lt IE 9]>
      <script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
      <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
    <![endif]-->
    </head>
    <body>
        <div class="container">
            <nav>
                <li><a href="#">Home</a></li>
                <li><a href="#">About Us</a></li>
                <li><a href="#">Products</a></li>
            </nav>
            {% block content %}{% endblock %}
            <footer>
                <p>All Rights Reserved</p>
            </footer>
        </div>
    </body>
</html>

HERE,

  • <html>...</html> defines a standard HTML5 document and loads Bootstrap CSS from a CDN network for styling purposes
  • <nav>...</nav> defines a simple navigation bar with three (3) links. This is the part common to all pages.
  • {% block content %}{% endblock %} defines a block section called content. This part of the parent template will dynamically be populated based on the page that the user has requested for.
  • <footer>...</footer> defines a footer section that will be common to all pages.

Next, create a file index.html in the directory /bookstore/templates and add the following code to it.

{% extends "base.html" %}

{% block content %}
 <h1>Welcome to our online bookstore</h1>
{% endblock %}

HERE,

  • {% extends "base.html" %} the tag extends is used to make the page index.html inherit from the parent page base.html. This will make available all elements defined in base.html to our child page index.html
  • {% block content %} defines a block section called content that will have markup that is unique to the page index.html. Remember we defined a content block section in base.html file also. The section in the parent file will be replaced with the one that we define in the child template.

In the previous lesson, we created a views.py file in the project directory /bookstore/bookstore and defined a function home_page that returned an HttpResponse object.

Open the views.py file and replace its contents with the following code

from django.shortcuts import render

def home_page(request):
    return render(request, 'index.html')

HERE,

  • from django.shortcuts import render imports the render function from the shortcuts module that is in the package django.
  • return render(request, 'index.html') loads the template index.html and retursn the HttpResponse object back which is the loaded in the browser for the user.

Run the following command to start the built-in server

python manage.py runserver

Next load the following URL in your web browser

http://127.0.0.1:8000

You should be able to see the following page

Django Template Inheritance

We get the above page as if all elements were defined in index.html but in reality, the various components come from more than one file. The advantage of this method is making changes in base.html makes them available to all the pages on the site.

Passing data to templates

In most cases, when you load a template, it will be accompanied by some data from the database or any source that your application uses. In this section, we will learn how to pass data parameters to the template.

Open the file /bookstore/bookstore/views.py and modify the home_page function as follows

from django.shortcuts import render

def home_page(request):
    data = {
        'sitename':'KodeBlog Shop'
    }

    return render(request, 'index.html',data)

HERE,

  • data = {...} defines a dictionary that defines a key sitename that has a value of KodeBlog Shop. This can have as many keys and values as we want
  • return render(request, 'index.html',data) passes in the variable data as the third argument. This makes the keys defined in data available as variables in the template index.html

Next update the template index.html to the following

{% extends "base.html" %}

{% block content %}
 <h1>Welcome to {{sitename}}</h1>
{% endblock %}

HERE,

  • <h1>Welcome to {{sitename}}</h1> we use double curly brackets to output the value of our variable sitename

Refresh the homepage in the web browser and you should be able to see the following variable value in the browser

Django Template Pass Data

Static Files

Statics Include the statics files that our template always needs. They include CSS styling, JavaScript libraries, images like icons, etc. We define a separate directory for the static files.

Create a new folder called static in our project root directory which is bookstore

Next, we need to add it to our settings file settings.py

At the bottom of the settings.py file just below STATIC_URL = '/static/', add the following line

STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static/'),]

HERE,

  • STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static/'),] sets the full path to the static directory and assigns the value to the variable STATICFILES_DIRS

In the next section, we will learn how to use static files.

Course Project URLs

Let's now define the URLs that will load our templates.

Open /books/urls.py and update the code as follows

from django.urls import path
from books.views import index, show, edit, create, search

urlpatterns = [
    path('books', index, name = 'books.index'),
    path('books/<int:pk>', show, name = 'books.show'),
    path('books/<int:pk>/edit', edit, name = 'books.edit'),
    path('books/create', create, name = 'books.create'),
    path('books/search', search, name = 'books.search'),
]

HERE,

  • from django.urls import path imports the path module
  • from books.views import index, show, edit, create, search imports the functions that we will define in /books/views.py module.
  • path('books', index, name = 'books.index'), defines a path /books that calls the index function. The urlpattern name is books.index. We will use this name in our templates to create links to /books. This makes our application very flexible because when we change the path from say /books to /catalogues, we don't have to change anything in our templates.
  • path('books/<int:pk>', show, name = 'books.show'), defines a pattern that accepts a URL parameter of int type i.e. /books/13.
  • path('books/<int:pk>/edit', edit, name = 'books.edit'), defines the URL pattern for editing books
  • path('books/create', create, name = 'books.create'), defines a URL pattern for showing the form that creates a new book
  • path('books/search', search, name = 'books.search'), defines the URL pattern for searching for books.

Next, open /books/views.py and define the following functions

from django.shortcuts import render


def index(request):
    data = {
        'title':'Books Listing',
    }

    return render(request, 'books/list.html', data)


def show(request,pk):
    data = {
        'title':'Book Details',
    }

    return render(request, 'books/detail.html', data)


def edit(request,pk):
    data = {
        'title':'Edit Book',
    }

    return render(request, 'books/update.html', data)


def create(request):
    data = {
        'title':'Create Book',
    }

    return render(request, 'books/create.html', data)


def search(request):
    data = {
        'title':'Search Books',
    }

    return render(request, 'books/list.html', data)

HERE,

  • The above functions accept a request object that is supplied automatically, creates context data and returns an HttpResponse object using the render function.

Course Project Templates

Now that we covered the basics, let's create the templates for our tutorial project. We will work with a free simple Bootstrap template Bare Template which you can download here for free.

Our Project Templates will be structured as follows

$ bookstore
.
├── authors
│   └── templates
│       └── authors
│           ├── create.html
│           ├── detail.html
│           ├── list.html
│           └── update.html
├── books
│   └── templates
│       └── books
│           ├── create.html
│           ├── detail.html
│           ├── list.html
│           └── update.html
├── categories
│   └── templates
│       └── categories
│           ├── create.html
│           ├── detail.html
│           ├── list.html
│           └── update.html
├── static
│   ├── css
│   ├── images
│   └── vendor
└── templates
    └── base.html
    └── index.html

Open the file /bookstore/templates/base.html and replace the contents with the following.

{% load static %}
<!DOCTYPE html>
<html lang="en">

    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
        <meta name="description" content="">
        <meta name="author" content="">
        <title>{{title}}</title>
        <link rel="shortcut icon" href="{% static "images/favicon.png" %}">
        <!-- Bootstrap core CSS -->
        <link href="{% static "vendor/bootstrap/css/bootstrap.min.css" %}" rel="stylesheet">
        <link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
        <link href="{% static "css/style.css" %}" rel="stylesheet">
    </head>
    <body>
        <!-- Navigation -->
        <nav class="navbar navbar-expand-lg navbar-dark bg-dark static-top">
            <div class="container">
                <a class="navbar-brand" href="{% url 'home' %}">KODEBLOG Bookstore</a>
                <button class="navbar-toggler" type="button"
                    data-toggle="collapse" data-target="#navbarResponsive"
                    aria-controls="navbarResponsive" aria-expanded="false"
                    aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="collapse navbar-collapse" id="navbarResponsive">
                    <ul class="navbar-nav ml-auto">
                        <li class="nav-item active">
                            <a class="nav-link" href="{% url 'home' %}">Home
                                <span class="sr-only">(current)</span>
                            </a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link" href="{% url 'books.index' %}">Books</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link" href="{% url 'authors.index' %}">Authors</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link" href="{% url 'categories.index' %}">Categories</a>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
        <!-- Page Content -->
        <div class="container">
            {% block content %}{% endblock %}
        </div>
        <!-- Bootstrap core JavaScript -->
        <script src="{% static "vendor/jquery/jquery.slim.min.js" %}"></script>
        <script src="{% static "vendor/bootstrap/js/bootstrap.bundle.min.js" %}"></script>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
        <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
        {% block scripts %}{% endblock %}
    </body>
</html>

HERE,

  • {% load static %} tells the template file that you should use Django static. Now, it will detect a static tag
  • <link rel="stylesheet" href="{% static "vendor/bootstrap/css/bootstrap.min.css" %}"> This is the static tag. Instead of giving the URL of /static, we use this tag. Since we have static_root = /static, this tag will be converted to /static/vendor/bootstrap/css/bootstrap.min.css. So, if you need to change it to /assets sometimes, you won't need to change all templates for just a simple change.
  • {% block content %}{% endblock %} these are the blocks. Now, if you create a template base on this template, you just call this block and put content in it, Django merges the base and extended.
  • {% block scripts %}{% endblock %} this block will be used to inject scripts that are specific to the particular page.

Next open the file /bookstore/templates/index.html and update the code as follows

{% extends "base.html" %}
{% block content %}
<div class="row search-bar">
    <form class="form" method="get">
        <div class="form-group col-md-12">
            <input type="text" id="title" class="form-control search-title"
                name="title" placeholder="Enter the title of book" autocomplete="off">
        </div>
    </form>
</div>
{% endblock %}

HERE,

  • {% extends "base.html" %} extends the base template
  • {% block content %} defines a block section called content.

We will not include the individual files for the applications to make it simple but you can use the download link below to download the template files for this lesson.

Summary

Templates are HTML files that contain Django special tags which are interpreted at run time. Double curly brackets {{}} are used to output variable values while {% .... %} is used for special tasks like if statements, while loops, call functions etc. Static files refers to resources such as JS, CSS, Images etc and you need to configure static files management in the settings.py file and create the static directory. If each app has its own templates, then you should set the setting APP_DIRS to TRUE so that Django first looks for the files in the respective application directory and if they dont exit then it can check in the root templates directory.

Author: Rodrick Kazembe

Rodrick is a developer who works on Desktop, Web and Mobile Applications. He is familiar with Python, Java, JavaScript, C++, C#, Kotlin, PHP, Python and the list goes on. Rodrick enjoys sharing knowledge especially when it comes to technology.

Django Admin Interface

Django Views

Leave A Reply