Of course! The concept of "including" content in Flask is fundamental and is handled by a core feature called Templates. This allows you to create a consistent layout for your website and reuse it across different pages, avoiding code duplication.

Here’s a complete guide covering the most common ways to "include" content in Flask, from the standard method to more advanced techniques.
The Core Concept: Flask Templates (Jinja2)
Flask uses the Jinja2 templating engine. This allows you to separate your Python application logic from your presentation (HTML).
The main idea is:
- Base Template (
layout.html): A skeleton HTML file that defines the common structure of your site (e.g.,<html>,<head>,<header>,<footer>). - Child Templates (
index.html,about.html): Specific HTML pages that "extend" the base template and fill in the content for that specific page.
This is the most powerful and recommended way to "include" content.

Method 1: The Standard Way - extends and block
This is the primary method for creating reusable layouts.
Step 1: Set Up Your Project Structure
Organize your files like this. The templates folder is required by Flask.
my_flask_app/
├── app.py
└── templates/
├── layout.html # The master template
├── index.html # Home page
└── about.html # About page
Step 2: Create the Base Template (templates/layout.html)
This file contains the common structure. Notice the {% block %} tags. These are named placeholders that child templates can fill.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">{% block title %}My Awesome Site{% endblock %}</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
</head>
<body>
<!-- A reusable navigation bar -->
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<a class="navbar-brand" href="#">Flask Inclusion</a>
<div class="collapse navbar-collapse">
<ul class="navbar-nav mr-auto">
<li class="nav-item"><a class="nav-link" href="{{ url_for('index') }}">Home</a></li>
<li class="nav-item"><a class="nav-link" href="{{ url_for('about') }}">About</a></li>
</ul>
</div>
</nav>
<div class="container mt-4">
<!-- This is the main content area -->
{% block content %}{% endblock %}
</div>
<!-- A reusable footer -->
<footer class="footer mt-5 py-3 bg-light">
<div class="container text-center">
<span class="text-muted">© 2025 My Awesome Site. All rights reserved.</span>
</div>
</footer>
</body>
</html>
Step 3: Create a Child Template (templates/index.html)
This page will "extend" the layout.html and provide content for the title and content blocks.

<!-- Extend the base layout -->
{% extends "layout.html" %}
<!-- Override the title block -->
{% block title %}Home - My Awesome Site{% endblock %}
<!-- Override the content block -->
{% block content %}
<div class="jumbotron">
<h1 class="display-4">Hello, World!</h1>
<p class="lead">This is the homepage of our Flask application. It uses a base template to keep the layout consistent.</p>
<hr class="my-4">
<p>This page was generated by extending <code>layout.html</code>.</p>
<a class="btn btn-primary btn-lg" href="{{ url_for('about') }}" role="button">Learn more</a>
</div>
{% endblock %}
Step 4: Create Another Child Template (templates/about.html)
This reuses the same layout but with different content.
<!-- Extend the same base layout -->
{% extends "layout.html" %}
<!-- Override the title block -->
{% block title %}About Us - My Awesome Site{% endblock %}
<!-- Override the content block -->
{% block content %}
<h2>About Our Project</h2>
<p>This project demonstrates how to use template inheritance in Flask to create a maintainable and consistent web application.</p>
<p>We are using the power of Jinja2 to keep our code D.R.Y. (Don't Repeat Yourself).</p>
{% endblock %}
Step 5: Write the Flask Application (app.py)
This Python file sets up the routes and renders the templates.
from flask import Flask, render_template
# Create a Flask application instance
app = Flask(__name__)
# Define a route for the home page
@app.route('/')
def index():
# Render the index.html template
return render_template('index.html')
# Define a route for the about page
@app.route('/about')
def about():
# Render the about.html template
return render_template('about.html')
# Run the application
if __name__ == '__main__':
app.run(debug=True)
Now, when you run app.py and go to http://127.0.0.1:5000/, you'll see the home page. The navigation and footer are "included" from layout.html. If you click the "About" link, you'll see the about page, which uses the exact same layout and footer, but with a different title and main content.
Method 2: Including Reusable Snippets (include)
Sometimes you have a piece of HTML that you want to reuse on many pages, but it's not a full section like a header or footer. For this, Jinja2 provides the {% include %} tag.
Let's say you have a standard alert box that you want to use in multiple places.
Step 1: Create the Snippet (templates/_alert.html)
By convention, reusable snippets are often prefixed with an underscore _. This is not required but helps identify them in the file browser.
<!-- templates/_alert.html -->
<div class="alert alert-warning alert-dismissible fade show" role="alert">
{{ message }}
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
Step 2: Include the Snippet in a Template
Now, you can include this snippet wherever you need it.
<!-- templates/index.html -->
{% extends "layout.html" %}
{% block content %}
<h1>Welcome!</h1>
<p>Here is some important information:</p>
<!-- Include the alert snippet here -->
{% include "alert.html" with message="This is a warning message included from a snippet!" %}
<p>More content can go here...</p>
{% endblock %}
When index.html is rendered, Jinja2 will find _alert.html, insert its HTML, and replace the {{ message }} variable with the value you provided.
Method 3: Including Macros (macro)
Macros are like functions in your templates. They are perfect for creating complex, reusable UI components like forms, buttons, or table rows.
Step 1: Define a Macro in a File (templates/_macros.html)
It's good practice to put your macros in a separate file.
<!-- templates/_macros.html -->
{% macro render_input_field(field_type, field_name, placeholder="") -%}
<div class="form-group">
<label for="{{ field_name }}">{{ field_name|capitalize }}</label>
<input type="{{ field_type }}"
class="form-control"
id="{{ field_name }}"
name="{{ field_name }}"
placeholder="{{ placeholder }}">
</div>
{%- endmacro %}
{% macro ... %}defines the macro.- controls whitespace stripping, which is useful for keeping your HTML clean.
- The parameters (
field_type,field_name, etc.) work just like function arguments.
Step 2: Import and Use the Macro
In your template, you must first import the file containing the macro.
<!-- templates/about.html -->
{% extends "layout.html" %}
<!-- Import the file containing the macro -->
{% from "_macros.html" import render_input_field %}
{% block content %}
<h2>Contact Us</h2>
<form>
<!-- Use the macro, passing arguments -->
{{ render_input_field('text', 'full_name', 'Enter your full name') }}
{{ render_input_field('email', 'email_address', 'name@example.com') }}
{{ render_input_field('textarea', 'message', 'Your message here...') }}
<button type="submit" class="btn btn-primary">Submit</button>
</form>
{% endblock %}
Summary: Which Method to Use?
| Method | Jinja2 Tag | Best For... | Example |
