Why template inheritance matters
A lot of beginners start by creating each page as a separate HTML file with its own <head>, navigation bar, footer, and styles. That works for two pages. It becomes a headache at ten.
The moment your app has a homepage, dashboard, blog list, contact page, and account pages, repeated markup turns into a maintenance problem. Change the navigation once, and suddenly you have to update five different files.
In practice, that means your app becomes easier to scale, easier to restyle, and much easier to reason about.
The core idea
Django templates use two key template tags for inheritance:
- {% extends "base.html" %} tells a template to inherit from a parent.
- {% block content %}{% endblock %} defines a replaceable section.
The parent template declares the structure. The child template replaces one or more named blocks.
{# parent template #}
<main>
{% block content %}{% endblock %}
</main>
{# child template #}
{% extends "base.html" %}
{% block content %}
<h1>Hello from a child template</h1>
{% endblock %}
Once this clicks, Django templates stop feeling repetitive and start feeling composable.
Building a base template
Your base template should contain the HTML skeleton shared by most pages:
- document structure
- site header and navigation
- footer
- global CSS and JS links
- named blocks for page-specific content
<!-- templates/base.html -->
{% load static %}
<!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 Django Site{% endblock %}</title>
<link rel="stylesheet" href="{% static 'css/site.css' %}">
{% block extra_head %}{% endblock %}
</head>
<body>
<header>
<nav>
<a href="/">Home</a>
<a href="/articles/">Articles</a>
<a href="/about/">About</a>
</nav>
</header>
<main class="container">
{% block content %}{% endblock %}
</main>
<footer>
<p>© 2026 My Django Site</p>
</footer>
<script src="{% static 'js/site.js' %}"></script>
{% block extra_scripts %}{% endblock %}
</body>
</html>
This base layout defines four useful blocks:
title
Lets each page set its own browser tab title.
extra_head
Good for page-specific meta tags, styles, or preload hints.
content
The main body of the page.
extra_scripts
Lets a page load only the JavaScript it actually needs.
Creating child templates
A child template starts with extends, then overrides the blocks it needs. It does not repeat the entire page structure.
<!-- templates/pages/home.html -->
{% extends "base.html" %}
{% block title %}Home | My Django Site{% endblock %}
{% block content %}
<section class="hero">
<h1>Welcome to the site</h1>
<p>This page uses the shared layout from base.html.</p>
</section>
{% endblock %}
Another child template can reuse the same parent while rendering completely different content:
<!-- templates/pages/about.html -->
{% extends "base.html" %}
{% block title %}About | My Django Site{% endblock %}
{% block content %}
<h1>About us</h1>
<p>We build clean Django apps with reusable templates.</p>
{% endblock %}
Includes and partials
Inheritance handles full-page structure. Includes handle smaller reusable pieces. Think of them as partial templates for components like alerts, navbars, cards, or pagination.
<!-- templates/includes/alert.html -->
<div class="alert alert-{{ level|default:'info' }}">
{{ message }}
</div>
<!-- inside another template -->
{% include "includes/alert.html" with level="success" message="Profile updated." %}
Use include for small reusable fragments. Use extends for page-level structure. Keeping those roles separate helps templates stay clear.
Useful block patterns
You do not need dozens of blocks. A few well-chosen ones usually cover most real projects.
- Page title block. Make every page set a specific title for better usability and SEO.
- Main content block. This is the most important block and should exist in nearly every base template.
- Head extension block. Useful for per-page metadata or canonical links.
- Script block. Keeps page-specific JavaScript from loading site-wide.
For more complex apps, you can even use nested inheritance. For example, a dashboard section could inherit from base.html, and then dashboard subpages could inherit from dashboard_base.html.
<!-- templates/dashboard/dashboard_base.html -->
{% extends "base.html" %}
{% block content %}
<div class="dashboard-layout">
<aside>Sidebar</aside>
<section>
{% block dashboard_content %}{% endblock %}
</section>
</div>
{% endblock %}
<!-- templates/dashboard/reports.html -->
{% extends "dashboard/dashboard_base.html" %}
{% block title %}Reports | Dashboard{% endblock %}
{% block dashboard_content %}
<h1>Reports</h1>
<p>Metrics and summaries go here.</p>
{% endblock %}
This gives larger sections of your app their own reusable internal layout without abandoning the global site shell.
Common mistakes
Forgetting extends at the top
The extends tag should be the first template tag in the file. If it is buried lower, you can get confusing results.
Too many tiny blocks
Overengineering your layout with excessive blocks makes templates harder to follow. Start simple.
Repeating shared markup in child templates
If the navbar or footer keeps reappearing in page files, the base template is not doing enough.
Using includes instead of inheritance
Includes are great for fragments, but they are not a substitute for a true page layout.
Suggested folder structure
A clean template directory makes inheritance easier to manage, especially once your project grows beyond a few pages.
templates/
├── base.html
├── includes/
│ ├── alert.html
│ ├── navbar.html
│ └── pagination.html
├── pages/
│ ├── home.html
│ ├── about.html
│ └── contact.html
└── dashboard/
├── dashboard_base.html
├── overview.html
└── reports.html
This structure makes it obvious what is global, what is a reusable partial, and what belongs to a specific section.