Skip to main content

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:

html
<!-- 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>&copy; 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 title
  • extra_css: For page-specific CSS files
  • content: For the main content of the page
  • footer: For the footer content
  • extra_js: For page-specific JavaScript files

Extending a Base Template

Now, let's create a child template that extends this base template:

html
<!-- 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:

html
<!-- 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:

html
{% block sidebar %}{% endblock %}

Named Endblocks

For improved readability, especially with nested or complex templates, you can name your endblock statements:

html
{% 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:

  1. base.html - Main site template with overall structure
  2. dashboard_base.html - Extends base.html but adds dashboard-specific layout
  3. dashboard_profile.html - Extends dashboard_base.html for the profile page
html
<!-- 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 %}
html
<!-- 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:

html
<!-- 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:

html
<!-- 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

  1. Keep Block Names Semantic: Use descriptive names like content, sidebar, or header instead of block1, block2.

  2. Define Default Content: When appropriate, include default content in your base template blocks.

  3. Don't Overcomplicate: While nesting is possible, try to keep your template hierarchy simple.

  4. Be Consistent: Establish naming conventions for blocks and use them consistently across your project.

  5. Document Your Blocks: For larger projects, document available blocks in comments at the top of base templates.

html
<!--
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

  1. 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.

  2. Nested Blocks: Be careful with deeply nested blocks as they can make templates hard to maintain.

  3. 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

Exercises

  1. Basic Block Practice: Create a base template with at least 5 different blocks, then create 3 child templates that extend it.

  2. Multi-level Inheritance: Build a three-level template hierarchy for a blog: base → blog_base → blog_post.

  3. Component Library: Create a set of reusable components (card, alert, modal) using template blocks for customization.

  4. Dynamic Block Selection: In a view, conditionally choose which template to extend based on user preferences or device type.

  5. 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! :)