3. Advance Templates
In Django, templates are used to separate the HTML and business logic of an application. They allow for rendering dynamic data into static HTML, helping to keep the view layer clean and maintainable. Advanced Django template usage involves leveraging template inheritance, custom filters, tags, context processors, and more.
1. Template Inheritance
Template inheritance is one of the most powerful features of Django templates. It allows you to create a base template that contains common elements like headers, footers, and navigation, and then extend that base template in child templates.
Base Template (base.html
)
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>{% block title %}My Site{% endblock %}</title></head><body> <header> <h1>Welcome to My Site</h1> <nav> <ul> <li><a href="/">Home</a></li> <li><a href="/about/">About</a></li> <li><a href="/contact/">Contact</a></li> </ul> </nav> </header>
<main> {% block content %}{% endblock %} </main>
<footer> <p>© 2025 My Site</p> </footer></body></html>
Child Template (home.html
)
{% extends "base.html" %}
{% block title %}Home - My Site{% endblock %}
{% block content %} <h2>Welcome to the Home Page</h2> <p>This is where the content of the home page goes.</p>{% endblock %}
- Explanation:
- The
base.html
contains the structure that is common to all pages (header, footer, navigation). - The
home.html
extendsbase.html
, overriding thetitle
andcontent
blocks to provide page-specific content.
- The
2. Custom Template Filters
Django allows you to define custom template filters to apply logic directly in the template. For instance, you could create a filter to format dates or numbers in a specific way.
Custom Filter Example
Create a custom filter in a file called templatetags/custom_filters.py
:
from django import templateimport datetime
register = template.Library()
@register.filterdef format_date(value, date_format='%Y-%m-%d'): if isinstance(value, datetime.date): return value.strftime(date_format) return value
Using the Custom Filter in Templates
In your template, you need to load the custom filter before using it:
{% load custom_filters %}
<p>Today’s date: {{ today|format_date:"%B %d, %Y" }}</p>
- Explanation:
format_date
is a custom filter that takes a date and formats it according to the specifieddate_format
.- In the template,
today
(which is expected to be adatetime.date
object) will be formatted using the custom filter.
3. Custom Template Tags
In addition to filters, you can define custom template tags that allow you to execute more complex logic within the template. For example, a custom tag to display the latest posts from a blog:
Custom Tag Example
Create a custom tag in templatetags/blog_tags.py
:
from django import templatefrom blog.models import Post
register = template.Library()
@register.simple_tagdef latest_posts(count=5): return Post.objects.all().order_by('-created_at')[:count]
Using the Custom Tag in Templates
In your template, load the custom tag and use it:
{% load blog_tags %}
<h2>Latest Posts</h2><ul> {% latest_posts 5 as posts %} {% for post in posts %} <li>{{ post.title }} - {{ post.created_at|date:"F d, Y" }}</li> {% endfor %}</ul>
- Explanation:
- The
latest_posts
custom tag retrieves the latest posts from the database and returns a queryset. - We use the
{% latest_posts 5 as posts %}
syntax to assign the latest posts to a variableposts
, which is then looped through to display the post titles.
- The
4. Template Context Processors
Context processors are functions that return a dictionary of context data that is available globally to all templates. You can use context processors to provide site-wide data, such as user information, site settings, or common data that should be accessible across your application.
Creating a Context Processor
In context_processors.py
:
from django.conf import settings
def site_settings(request): return { 'site_name': settings.SITE_NAME, 'admin_email': settings.ADMIN_EMAIL, }
Register the Context Processor in settings.py
TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', 'yourapp.context_processors.site_settings', # Add this line ], }, },]
Using Context Data in Templates
Now, the site_name
and admin_email
values will be available in all templates:
<h1>Welcome to {{ site_name }}</h1><p>For inquiries, please contact {{ admin_email }}</p>
- Explanation:
- The
site_settings
context processor makessite_name
andadmin_email
available in all templates. - This is useful for global settings like the site name or admin email that are needed across multiple templates.
- The
5. Template Includes for Reusable Components
You can break up your templates into smaller, reusable components using the {% include %}
tag. This is useful for elements like navigation bars, footers, or repeated UI components.
Reusable Component (nav.html
)
<nav> <ul> <li><a href="/">Home</a></li> <li><a href="/about/">About</a></li> <li><a href="/contact/">Contact</a></li> </ul></nav>
Including the Component in Other Templates
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>{% block title %}My Site{% endblock %}</title></head><body> {% include 'nav.html' %} {% block content %}{% endblock %}</body></html>
- Explanation:
- The
nav.html
file contains the markup for the navigation menu. - The
{% include 'nav.html' %}
tag inbase.html
allows you to include the navigation bar in multiple templates.
- The
6. Template for Dynamic Forms
You can render dynamic forms in templates, making them flexible and reusable.
Form Definition in forms.py
from django import forms
class ContactForm(forms.Form): name = forms.CharField(max_length=100) email = forms.EmailField() message = forms.CharField(widget=forms.Textarea)
Rendering the Form in a Template
<h2>Contact Us</h2>
<form method="POST"> {% csrf_token %} {{ form.as_p }} <button type="submit">Submit</button></form>
- Explanation:
- The form is rendered dynamically using
{{ form.as_p }}
, which renders each form field inside a<p>
tag. You can also use other render options like{{ form.as_table }}
or manually loop over form fields.
- The form is rendered dynamically using