Django Template Blocks
Template blocks are one of Django's most powerful template features, allowing you to create reusable base templates and override specific sections as needed. This template inheritance system makes maintaining consistent layouts across your website while customizing individual pages effortless.
Introduction to Template Blocks
In Django, you often want to share common elements (like headers, footers, and navigation) across all pages while allowing each page to have unique content. Template blocks solve this problem by defining "slots" in parent templates that child templates can fill with their own content.
Think of template blocks as placeholders that can be overridden or extended by templates that inherit from a base template.
The Basics of Template Blocks
Creating a Base Template
Let's start by creating a base template that will serve as the foundation for all other pages:
<!-- base.html -->
<!DOCTYPE html>
<html>
<head>
<title>{% block title %}My Django Site{% endblock %}</title>
<link rel="stylesheet" href="/static/css/style.css">
{% block extra_css %}{% endblock %}
</head>
<body>
<header>
<h1>My Django Website</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 %}
<p>Default content</p>
{% endblock %}
</main>
<footer>
{% block footer %}
<p>© 2023 My Django Website</p>
{% endblock %}
</footer>
<script src="/static/js/main.js"></script>
{% block extra_js %}{% endblock %}
</body>
</html>
In this base template, we've defined several blocks:
title
: For the page titleextra_css
: For page-specific CSS filescontent
: For the main content of the pagefooter
: For the footer contentextra_js
: For page-specific JavaScript files
Extending a Base Template
Now, let's create a child template that extends this base template:
<!-- about.html -->
{% extends "base.html" %}
{% block title %}About Us | My Django Site{% endblock %}
{% block content %}
<h2>About Our Company</h2>
<p>We are a team of passionate developers building awesome web applications!</p>
<div class="team-members">
<h3>Our Team</h3>
<ul>
<li>John Doe - CEO</li>
<li>Jane Smith - CTO</li>
<li>Bob Johnson - Lead Developer</li>
</ul>
</div>
{% endblock %}
{% block extra_css %}
<link rel="stylesheet" href="/static/css/about.css">
{% endblock %}
When Django renders about.html
, it will use the structure from base.html
but replace the title
, content
, and extra_css
blocks with the content specified in about.html
.
Advanced Block Techniques
Super Blocks - Extending Block Content
Sometimes you want to add to a block's content rather than completely replace it. The {{ block.super }}
variable allows you to include the parent template's content for a block:
<!-- contact.html -->
{% extends "base.html" %}
{% block title %}Contact Us | My Django Site{% endblock %}
{% block content %}
<h2>Contact Us</h2>
<form method="post">
{% csrf_token %}
<div class="form-group">
<label for="name">Name:</label>
<input type="text" id="name" name="name" required>
</div>
<div class="form-group">
<label for="email">Email:</label>
<input type="email" id="email" name="email" required>
</div>
<div class="form-group">
<label for="message">Message:</label>
<textarea id="message" name="message" required></textarea>
</div>
<button type="submit">Send Message</button>
</form>
{% endblock %}
{% block footer %}
{{ block.super }}
<p>Contact us at: [email protected]</p>
{% endblock %}
In this example, the footer will contain both the copyright message from the base template AND the additional contact email.
Empty Blocks
You can create empty blocks in your base template that child templates can optionally fill:
{% block sidebar %}{% endblock %}
Named Endblocks
For improved readability, especially with nested or complex templates, you can name your endblock statements:
{% block content %}
<h2>Welcome to our site</h2>
<p>This is the homepage content.</p>
{% endblock content %}
Practical Examples
Multi-level Template Inheritance
You can create multiple levels of templates. For example, a site might have:
base.html
- Main site template with overall structuredashboard_base.html
- Extends base.html but adds dashboard-specific layoutdashboard_profile.html
- Extends dashboard_base.html for the profile page
<!-- dashboard_base.html -->
{% extends "base.html" %}
{% block content %}
<div class="dashboard-container">
<aside class="dashboard-sidebar">
<ul>
<li><a href="/dashboard/">Overview</a></li>
<li><a href="/dashboard/profile/">Profile</a></li>
<li><a href="/dashboard/settings/">Settings</a></li>
</ul>
</aside>
<div class="dashboard-main">
{% block dashboard_content %}{% endblock %}
</div>
</div>
{% endblock %}
<!-- dashboard_profile.html -->
{% extends "dashboard_base.html" %}
{% block title %}Your Profile | My Django Site{% endblock %}
{% block dashboard_content %}
<h2>Your Profile</h2>
<div class="profile-section">
<img src="{{ user.profile.avatar.url }}" alt="Profile Picture">
<h3>{{ user.get_full_name }}</h3>
<p>Username: {{ user.username }}</p>
<p>Email: {{ user.email }}</p>
</div>
<div class="edit-profile-section">
<h3>Edit Your Details</h3>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Save Changes</button>
</form>
</div>
{% endblock %}
Including Blocks in Components
You can also use blocks within included templates to make components more flexible:
<!-- components/card.html -->
<div class="card {% block card_class %}{% endblock %}">
<div class="card-header">
{% block card_header %}Default Header{% endblock %}
</div>
<div class="card-body">
{% block card_body %}
<p>Default card body content</p>
{% endblock %}
</div>
<div class="card-footer">
{% block card_footer %}{% endblock %}
</div>
</div>
Then in your templates:
<!-- product_detail.html -->
{% extends "base.html" %}
{% block content %}
<h2>{{ product.name }}</h2>
{% include "components/card.html" with card_title=product.name %}
{% block card_class %}product-card{% endblock %}
{% block card_header %}{{ product.name }} - ${{ product.price }}{% endblock %}
{% block card_body %}
<img src="{{ product.image.url }}" alt="{{ product.name }}">
<p>{{ product.description }}</p>
{% endblock %}
{% block card_footer %}
<button class="add-to-cart" data-product-id="{{ product.id }}">
Add to Cart
</button>
{% endblock %}
{% include %}
{% endblock %}
Best Practices for Using Template Blocks
-
Keep Block Names Semantic: Use descriptive names like
content
,sidebar
, orheader
instead ofblock1
,block2
. -
Define Default Content: When appropriate, include default content in your base template blocks.
-
Don't Overcomplicate: While nesting is possible, try to keep your template hierarchy simple.
-
Be Consistent: Establish naming conventions for blocks and use them consistently across your project.
-
Document Your Blocks: For larger projects, document available blocks in comments at the top of base templates.
<!--
Available blocks:
- title: Page title
- content: Main page content
- sidebar: Optional sidebar content
- extra_css: Additional CSS files
- extra_js: Additional JS files
-->
Common Pitfalls
-
Block Scope: Blocks can't access variables defined in child templates. Variables must be defined in the template where they're used or passed from the view.
-
Nested Blocks: Be careful with deeply nested blocks as they can make templates hard to maintain.
-
Overriding vs Extending: Remember the difference between completely overriding a block versus extending it with
{{ block.super }}
.
Summary
Django template blocks are the cornerstone of Django's template inheritance system. They allow you to:
- Create reusable base templates with common elements
- Override specific sections in child templates
- Build complex, multi-level template hierarchies
- Maintain a consistent look and feel across your site while allowing page-specific customization
By mastering template blocks, you'll write more maintainable templates and avoid code duplication in your Django projects.
Additional Resources and Exercises
Resources
- Django Official Documentation on Template Inheritance
- Two Scoops of Django - Contains excellent best practices for Django templates
Exercises
-
Basic Block Practice: Create a base template with at least 5 different blocks, then create 3 child templates that extend it.
-
Multi-level Inheritance: Build a three-level template hierarchy for a blog: base → blog_base → blog_post.
-
Component Library: Create a set of reusable components (card, alert, modal) using template blocks for customization.
-
Dynamic Block Selection: In a view, conditionally choose which template to extend based on user preferences or device type.
-
Challenge: Create a dashboard template with a sidebar that highlights the current page and content blocks that change based on the selected section.
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)