Django Templates Introduction
What are Django Templates?
Django templates are a powerful way to generate HTML dynamically. They form an essential part of Django's MVT (Model-View-Template) architecture, serving as the presentation layer of your web application. Templates allow you to separate the design of your pages from the Python code that powers your application.
At their core, Django templates are text files that can generate any text-based format like HTML, XML, CSV, etc. They contain static content as well as special syntax that describes how dynamic content will be inserted.
Why Use Templates?
Before diving into templates, let's understand why they're important:
- Separation of Concerns: Templates separate HTML/presentation from Python business logic
- Code Reusability: Common elements like headers and footers can be reused across multiple pages
- Designer-Developer Workflow: Designers can work on templates while developers focus on Python code
- Security: Django's template system automatically escapes variables to prevent XSS attacks
Template Basics
A Django template is essentially an HTML file with additional template tags and variables. Let's look at a simple example:
<!DOCTYPE html>
<html>
<head>
<title>{{ page_title }}</title>
</head>
<body>
<h1>Welcome to {{ site_name }}</h1>
<p>Hello, {{ user_name }}!</p>
</body>
</html>
In this example, {{ page_title }}
, {{ site_name }}
, and {{ user_name }}
are variables that will be replaced with actual values when the template is rendered.
Template Configuration
Django automatically looks for templates in your app's templates
directory. To set up templates:
- Create a
templates
folder in your Django app directory - Inside that folder, create another folder with the same name as your app (this prevents namespace collisions)
- Place your HTML templates inside this folder
For example, for an app named blog
, your structure would look like:
blog/
├── __init__.py
├── admin.py
├── apps.py
├── models.py
├── templates/
│ └── blog/
│ ├── index.html
│ └── post_detail.html
├── tests.py
├── urls.py
└── views.py
Rendering Templates
To render a template from a view, you'll use the render()
function. Here's a basic view that renders a template:
from django.shortcuts import render
def home_view(request):
context = {
'page_title': 'Home Page',
'site_name': 'My Awesome Website',
'user_name': 'John Doe'
}
return render(request, 'myapp/home.html', context)
The render()
function takes three arguments:
- The request object
- The path to the template
- A dictionary (context) containing the data you want to pass to the template
When this view is executed, it will render the home.html
template with the variables from the context dictionary.
Template Variables
As we've seen, you can pass variables to templates using the context dictionary. To use these variables in your template, you enclose them in double curly braces:
<h1>{{ variable_name }}</h1>
You can also access attributes of variables using dot notation:
<p>Author: {{ post.author }}</p>
<p>Published: {{ post.date_published }}</p>
Template Tags
Django templates also include template tags, which provide programming-like functionality within your templates. Template tags are enclosed in {% %}
brackets.
Here are some common template tags:
For Loops
<ul>
{% for item in items %}
<li>{{ item }}</li>
{% endfor %}
</ul>
If Statements
{% if user.is_authenticated %}
<p>Welcome, {{ user.username }}!</p>
{% else %}
<p>Please log in.</p>
{% endif %}
URL Tag
<a href="{% url 'post_detail' post.id %}">Read more</a>
Template Filters
Filters transform variable values before displaying them. They're applied using a pipe (|
) character:
<p>Posted {{ post.date|date:"F j, Y" }}</p>
<p>{{ post.content|truncatewords:50 }}</p>
Common filters include:
lower
: Converts text to lowercaseupper
: Converts text to uppercaselength
: Returns the length of a string or listdate
: Formats a date according to a specified formattruncatewords
: Truncates a string after a certain number of words
Template Inheritance
One of the most powerful features of Django's template system is template inheritance. It allows you to build a base template containing common elements and then extend it in child templates.
Base Template (base.html)
<!DOCTYPE html>
<html>
<head>
<title>{% block title %}My Site{% endblock %}</title>
<link rel="stylesheet" href="/static/css/main.css">
</head>
<body>
<header>
<h1>My Website</h1>
<nav>
<a href="/">Home</a>
<a href="/about/">About</a>
<a href="/contact/">Contact</a>
</nav>
</header>
<main>
{% block content %}
{% endblock %}
</main>
<footer>
<p>© 2023 My Website</p>
</footer>
</body>
</html>
Child Template (home.html)
{% extends "myapp/base.html" %}
{% block title %}Home | My Site{% endblock %}
{% block content %}
<h2>Welcome to the homepage!</h2>
<p>This is the content specific to the home page.</p>
{% endblock %}
In this example:
- The
{% extends %}
tag specifies which template to inherit from - The
{% block %}
and{% endblock %}
tags define sections that can be overridden in child templates - The child template only needs to define the content that's different from the base template
Practical Example: A Blog Post List
Let's put everything together to create a simple blog post listing page:
models.py:
from django.db import models
class BlogPost(models.Model):
title = models.CharField(max_length=200)
author = models.CharField(max_length=100)
content = models.TextField()
published_date = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
views.py:
from django.shortcuts import render
from .models import BlogPost
def post_list(request):
posts = BlogPost.objects.all().order_by('-published_date')
return render(request, 'blog/post_list.html', {'posts': posts})
post_list.html:
{% extends "blog/base.html" %}
{% block title %}Blog Posts | My Site{% endblock %}
{% block content %}
<h2>Latest Blog Posts</h2>
{% if posts %}
{% for post in posts %}
<article class="post">
<h3>{{ post.title }}</h3>
<p class="meta">By {{ post.author }} on {{ post.published_date|date:"F j, Y" }}</p>
<div class="content">
{{ post.content|truncatewords:30 }}
</div>
<a href="{% url 'post_detail' post.id %}">Read more</a>
</article>
{% endfor %}
{% else %}
<p>No posts available.</p>
{% endif %}
{% endblock %}
This example shows:
- A model to store blog posts
- A view that fetches posts and passes them to a template
- A template that displays the posts with formatting and filters
Summary
Django templates provide a powerful and flexible way to generate HTML content dynamically. They allow you to:
- Separate your presentation logic from business logic
- Pass data from views to templates using context dictionaries
- Use variables, filters, and tags to manipulate and display data
- Create reusable layouts through template inheritance
- Build complex web interfaces with minimal repetition
As you grow more familiar with Django's template system, you'll find it makes building complex web applications much more manageable and maintainable.
Additional Resources
Practice Exercises
- Create a base template for a personal portfolio site with headers and footers
- Build a template that displays a list of products with prices and apply filters to format the prices
- Create a template that uses conditional tags to display different content based on user authentication status
- Build a blog post detail page that extends your base template
- Experiment with using custom template tags and filters
By mastering Django templates, you'll be able to create sophisticated web interfaces while maintaining clean, organized code.
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)