Skip to main content

Templates in Flask (Part 1): Template Inheritance

We've learned how to use Flask's render_template() function to serve HTML files and pass variables to them. This is great, but as you build a website with multiple pages, you'll notice that a lot of your HTML is repetitive. The navigation bar, the footer, the <head> section with all your CSS links—these are the same on every page.

Copying and pasting this common HTML into every new template file is inefficient and a maintenance nightmare. If you need to change a link in your navigation bar, you'd have to edit every single file.

The solution to this is template inheritance, a powerful feature of the Jinja2 templating engine that allows you to create a base "skeleton" template and have other templates "inherit" from it.


📚 Prerequisites

You should know how to create a basic Flask app and use render_template() to serve an HTML file. Your project should have a templates folder.


🎯 Article Outline: What You'll Master

In this article, you will learn:

  • The DRY Principle in HTML: Understand why template inheritance is crucial for keeping your templates clean and maintainable.
  • Creating a Base Template: How to define a master layout with {% block %} tags as placeholders.
  • Creating a Child Template: How to use {% extends %} to inherit from a base template and fill in the blocks.
  • A Practical Example: Build a simple two-page site with a consistent header and footer.

🧠 Section 1: The Core Concept - Blocks

Template inheritance works by defining named blocks in a parent template. These blocks act as placeholders that child templates can fill with their own content.

The syntax for a block is:

{% block block_name %}
<!-- Default content can go here -->
{% endblock %}

💻 Section 2: Creating the Base Template

Let's create a master layout for our website. This file will contain all the common HTML, including the <html>, <head>, and <body> tags, as well as a navigation bar and a footer.

Create a file named base.html inside your templates folder.

templates/base.html:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<!-- This block allows the child template to set a unique title -->
<title>{% block title %}My Awesome Site{% endblock %}</title>
<style>
body { font-family: sans-serif; margin: 0; }
nav { background-color: #333; padding: 1rem; }
nav a { color: white; margin: 0 1rem; }
footer { text-align: center; padding: 1rem; margin-top: 2rem; background-color: #f2f2f2; }
.content { padding: 2rem; }
</style>
</head>
<body>

<nav>
<a href="{{ url_for('home') }}">Home</a>
<a href="{{ url_for('about') }}">About</a>
</nav>

<main class="content">
<!-- This is the main content block that child templates will fill -->
{% block content %}{% endblock %}
</main>

<footer>
<p>&copy; 2025 My Awesome Site</p>
</footer>

</body>
</html>

We have defined two blocks: title and content. The title block has some default content, while the content block is empty, waiting for a child template to provide the main page content.


🛠️ Section 3: Creating Child Templates

Now, let's create two pages, home.html and about.html, that will inherit from our base.html.

The {% extends "base.html" %} tag must be the very first thing in the child template. It tells Jinja2 to use base.html as the skeleton.

templates/home.html:

{% extends "base.html" %}

{% block title %}Home Page - My Awesome Site{% endblock %}

{% block content %}
<h1>Welcome to the Home Page!</h1>
<p>This is the main content for our home page. It's inserted directly into the content block of the base template.</p>
{% endblock %}

templates/about.html:

{% extends "base.html" %}

{% block title %}About Us{% endblock %}

{% block content %}
<h1>About Our Company</h1>
<p>We are a company that does awesome things!</p>
{% endblock %}

Notice how clean these files are. They only contain the content that is unique to each page. All the repetitive HTML is handled by base.html.


🚀 Section 4: Updating the Flask App

Finally, let's update our app.py to render these new templates.

from flask import Flask, render_template, url_for

app = Flask(__name__)

@app.route("/")
def home():
return render_template("home.html")

@app.route("/about")
def about():
return render_template("about.html")

Now, run your application.

  • When you visit /, Flask renders home.html. Jinja2 sees that it extends base.html, so it loads base.html and then injects the title and content blocks from home.html into the correct places.
  • When you visit /about, the same process happens with about.html.

You now have a two-page website with a consistent layout. If you need to change the footer, you only have to edit base.html once, and the change will appear on every page.


✨ Conclusion & Key Takeaways

Template inheritance is a fundamental technique for building maintainable web applications. It allows you to follow the DRY (Don't Repeat Yourself) principle in your HTML, just as functions do in your Python code.

Let's summarize the key takeaways:

  • Create a base.html file with the common layout for your entire site.
  • Use {% block block_name %} in your base template to define areas that child templates can override.
  • Use {% extends "base.html" %} at the very top of a child template to inherit from the base.
  • Fill in the blocks in the child template with the page-specific content.

➡️ Next Steps

We've seen how to create a consistent layout. In the next article, "Templates in Flask (Part 2): Control structures and filters," we'll explore more advanced Jinja2 features like loops and conditionals to make the content within our templates even more dynamic.

Happy building!