Django’s 'include' Template Tag
This article introduces Django’s {% include %} template tag and explains how to reuse small template fragments across pages. It covers context sharing, with, only, loops, reusable partials, template organization, inheritance differences, performance considerations, testing, and common mistakes..
Django’s include Template Tag
Django templates often contain pieces of HTML that appear in more than one place.
Examples include:
- navigation menus
- article cards
- user profile blocks
- pagination controls
- alert messages
- form field layouts
- sidebars
- reusable buttons
- table rows
Copying the same markup into several templates creates duplication.
Django’s {% include %} template tag helps solve this by rendering another template inside the current template.
A simple example looks like:
⧉
1 | |
Django loads articles/article_card.html, renders it using the current template context, and inserts the result at that position.
Conceptually:
⧉
1 2 3 4 5 6 7 | |
The include tag is useful for small reusable template fragments that belong inside a larger page.
What Does {% include %} Do?
The include tag renders another template and inserts its output into the current template.
Suppose the main template contains:
⧉
1 2 3 | |
And articles/article_card.html contains:
⧉
1 2 3 4 | |
If the current context contains:
⧉
1 2 3 | |
the included template can access that variable.
The final HTML might resemble:
⧉
1 2 3 4 5 6 | |
The included template is rendered before its output becomes part of the parent template.
Basic Syntax
The basic syntax is:
⧉
1 | |
For example:
⧉
1 | |
or:
⧉
1 | |
The path follows the same template lookup rules used by other Django template operations.
Why Use include?
The main reason is to avoid repeating markup.
Without include, several templates might contain the same card:
⧉
1 2 3 4 | |
If the design changes, every copy must be updated.
With an included template:
⧉
1 2 | |
the markup exists in one place.
Other templates can reuse it:
⧉
1 | |
This provides:
- less duplication
- easier maintenance
- more consistent markup
- smaller parent templates
- clearer separation of reusable UI pieces
A Simple Reusable Partial
Suppose an application displays user information in several places.
Create:
⧉
1 2 3 | |
Contents:
⧉
1 2 3 4 5 6 7 8 9 10 11 | |
Include it:
⧉
1 | |
The included template receives the current context by default.
Included Templates Receive the Current Context
Consider:
⧉
1 2 3 | |
Inside article_card.html:
⧉
1 2 3 4 5 | |
This works because the loop variable:
⧉
1 | |
is part of the current context when the include tag runs.
The included template can access it.
Using with
You can explicitly pass values into the included template using with.
Example:
⧉
1 | |
Inside the included template:
⧉
1 2 3 | |
Even though the parent variable is called:
⧉
1 | |
the partial receives it as:
⧉
1 | |
This can make reusable fragments easier to understand.
Passing Multiple Variables
You can pass several values:
⧉
1 | |
Included template:
⧉
1 2 3 | |
This allows one fragment to be used with different data.
For example:
⧉
1 | |
and:
⧉
1 | |
Variables Can Be Expressions
Values passed with with do not have to be literal strings.
Example:
⧉
1 | |
Or:
⧉
1 | |
Or:
⧉
1 | |
This makes included templates useful inside loops and nested object relationships.
Using only
By default, an included template receives the current context.
Sometimes that gives the partial access to more variables than it needs.
Use:
⧉
1 | |
The only option restricts the included template to the variables explicitly provided.
Conceptually:
⧉
1 2 3 4 5 6 7 | |
This can make a reusable template fragment more predictable.
Why only Can Be Useful
Suppose the parent template contains:
⧉
1 2 3 4 5 6 7 | |
but the partial only needs:
⧉
1 | |
You can write:
⧉
1 | |
Now the partial has a smaller and clearer dependency.
This is useful when you want the fragment to behave more like a small component.
Include Inside a Loop
One of the most common patterns is including a partial for each object in a collection.
Parent template:
⧉
1 2 3 4 5 6 7 8 9 | |
Partial:
⧉
1 2 3 4 5 6 7 8 9 10 11 | |
This keeps the list template focused on the list and the card template focused on one article.
Include Inside Conditional Logic
The include tag can be placed inside an if block.
Example:
⧉
1 2 3 4 5 | |
Django includes only the fragment for the branch that executes.
Dynamic Template Names
The template name can come from a variable.
Example:
⧉
1 | |
If:
⧉
1 | |
Django renders that template.
This can be useful when the application chooses a partial dynamically.
For example:
⧉
1 | |
Use dynamic includes carefully because they can make template flow harder to follow.
Static template paths are usually easier to understand.
Included Templates Are Independent Render Operations
An important detail is that the included template is rendered as a separate template fragment.
The parent template does not simply paste the source code into itself before rendering.
Conceptually:
⧉
1 2 3 4 5 6 7 | |
This affects how template blocks behave.
include Is Not Template Inheritance
The include tag and template inheritance solve different problems.
Template inheritance uses:
⧉
1 | |
and:
⧉
1 2 | |
It defines the overall page structure.
The include tag inserts a small fragment inside that structure.
A useful distinction is:
⧉
1 2 3 4 5 | |
For example:
⧉
1 2 3 4 5 6 7 8 | |
Example with Template Inheritance
base.html:
⧉
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | |
articles/list.html:
⧉
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
Inheritance defines the page hierarchy.
Includes provide reusable sections within that hierarchy.
Blocks Inside Included Templates
Suppose an included template contains:
⧉
1 2 3 | |
Do not expect a child template to override that block in the same way it overrides blocks from its parent template.
Included templates are rendered separately.
Use {% extends %} and {% block %} when you need inheritance and overriding behavior.
Use {% include %} when you need to render a fragment.
Reusable Navigation
A navigation bar is a common include.
Create:
⧉
1 2 3 | |
Contents:
⧉
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
Include it in a base template:
⧉
1 | |
Because the normal template context is inherited, the fragment can access user when that context variable is available.
Reusable Message Fragment
Suppose several layouts need to display Django messages.
Create:
⧉
1 2 3 | |
⧉
1 2 3 4 5 6 7 8 9 | |
Then:
⧉
1 | |
This prevents the same message-rendering markup from being repeated.
Reusable Form Field
A project may use a partial for manually rendered form fields.
Create:
⧉
1 2 3 | |
⧉
1 2 3 4 5 6 7 8 9 10 11 12 13 | |
Use it:
⧉
1 2 3 4 5 6 7 8 9 10 | |
This can help standardize form markup.
Reusable Button Fragment
A simple button partial:
⧉
1 2 3 4 5 6 | |
Usage:
⧉
1 | |
Another use:
⧉
1 | |
This works well for small repeated markup.
For highly configurable UI components, however, many template arguments can eventually make a partial difficult to understand.
Naming Included Templates
There is no Django requirement that included templates use a special filename convention.
Common approaches include:
⧉
1 2 3 | |
Some projects use a leading underscore:
⧉
1 2 | |
This indicates that the file is intended to be used as a partial rather than as a complete page.
For example:
⧉
1 2 3 4 5 | |
Then:
⧉
1 | |
The underscore is only a project convention.
Django does not treat it specially.
Organizing Template Partials
A simple project may use:
⧉
1 2 3 4 5 6 7 8 9 10 | |
Another structure might use:
⧉
1 2 3 4 5 | |
Both approaches are reasonable.
The important goal is that developers can easily find the fragment.
App-Level Includes
Reusable fragments that belong to one Django app can stay inside that app's template namespace.
For example:
⧉
1 2 3 4 5 6 | |
Include:
⧉
1 | |
This namespacing helps avoid collisions with similarly named templates from other apps.
Project-Level Includes
Fragments shared across several apps can live in a project-level template directory.
Example:
⧉
1 2 3 4 5 6 | |
Then:
⧉
1 | |
Passing Boolean-Like Values
Suppose a card can optionally show an image.
You might write:
⧉
1 | |
Inside:
⧉
1 2 3 4 5 6 | |
This can make one partial useful in several contexts.
However, if the partial collects too many configuration flags, it may be doing too much.
Avoid Too Many Include Arguments
This can become difficult to understand:
⧉
1 | |
A developer now has to understand many configuration options.
Sometimes separate fragments are clearer:
⧉
1 2 | |
or the presentation may deserve a custom inclusion tag or another component approach.
Use include for simple reusable markup.
Includes and Database Queries
An include itself does not automatically perform database queries.
However, variables accessed inside the included template may trigger lazy database work.
For example:
⧉
1 2 3 | |
Partial:
⧉
1 | |
If the articles were loaded without their authors, accessing:
⧉
1 | |
may result in additional database queries.
With many articles, this can cause an N+1 query problem.
The template include is not the cause by itself.
The issue is the data access performed while rendering it.
Avoiding N+1 Queries with Includes
View:
⧉
1 2 3 4 5 | |
Template:
⧉
1 2 3 | |
Partial:
⧉
1 2 3 4 5 6 7 8 9 | |
Using select_related("author") allows Django to retrieve the related author efficiently.
When a reusable partial accesses relationships, the view still needs to provide data efficiently.
Includes Should Not Hide Expensive Work
A small-looking parent template:
⧉
1 | |
may hide a large fragment with many loops and relationship lookups.
Reusability is useful, but it should not make performance invisible.
When debugging a slow page, inspect included templates as well as the parent template.
Missing Templates
If Django cannot find the included template:
⧉
1 | |
template rendering normally fails with:
⧉
1 | |
Check:
- the path spelling
- app namespacing
- template directories
INSTALLED_APPS- the project's template configuration
Template Path Mistakes
Given:
⧉
1 2 3 4 | |
use:
⧉
1 | |
Do not use the filesystem path:
⧉
1 | |
Template names are relative to configured template roots.
Passing the Wrong Variable
Suppose the partial expects:
⧉
1 | |
but the parent uses:
⧉
1 | |
The partial does not receive a variable named:
⧉
1 | |
It receives:
⧉
1 | |
Either change the include:
⧉
1 | |
or change the partial:
⧉
1 | |
Consistent variable names make partials easier to reuse.
Missing Variables Often Render Silently
Django templates generally render missing variables as empty output rather than raising a Python-style NameError.
Suppose:
⧉
1 2 3 | |
but article is not available.
The output may simply be empty.
This can make context mistakes harder to notice.
Using explicit:
⧉
1 | |
can make dependencies clearer during development.
Includes and Autoescaping
Included templates use Django's normal template rendering behavior, including autoescaping.
For example:
⧉
1 | |
will normally escape HTML-sensitive characters.
The fact that the markup lives inside an included template does not change Django's standard escaping rules.
Include Versus Custom Template Tags
For simple reusable markup, include is often enough.
Example:
⧉
1 | |
A custom inclusion tag can be more appropriate when the reusable component needs Python logic or must build its own context.
Conceptually:
⧉
1 2 3 4 5 6 7 8 9 10 11 | |
Start with include when no Python-side logic is necessary.
Include Versus a View
Do not create a separate view merely to render every reusable fragment.
For example, an article card inside an article list usually does not need:
⧉
1 | |
and another HTTP request.
Use:
⧉
1 | |
inside the existing page request.
A separate view is appropriate when the fragment truly represents a separate endpoint, such as:
- an AJAX request
- an HTMX endpoint
- a standalone resource
- independently refreshed data
Include Versus JavaScript Components
The include tag is server-side template composition.
The server renders:
⧉
1 | |
before sending HTML to the browser.
Conceptually:
⧉
1 2 3 4 5 6 7 8 9 | |
A React or JavaScript component is usually rendered or managed on the client side.
These are different approaches.
For a traditional Django-rendered application, include is often enough for reusable HTML fragments.
Include Versus Template Inheritance
A useful rule is:
⧉
1 2 3 4 5 6 7 | |
For example:
⧉
1 2 3 4 5 6 7 8 | |
Includes Can Be Nested
An included template can itself include another template.
For example:
⧉
1 2 3 4 5 | |
article_card.html:
⧉
1 2 3 4 5 6 7 | |
This can be useful, but excessive nesting makes templates harder to follow.
Keep the structure reasonably shallow.
A Complete Article Card Example
Model:
⧉
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | |
View:
⧉
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | |
Parent template:
⧉
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
Included template:
⧉
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | |
The parent controls the list.
The included template controls the presentation of one article.
A Pagination Partial
Pagination is another good candidate for an include.
Create:
⧉
1 | |
⧉
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | |
Use:
⧉
1 | |
The same fragment can be reused on several list pages.
An Empty-State Partial
Create:
⧉
1 | |
⧉
1 2 3 4 5 6 7 8 9 10 11 | |
Use:
⧉
1 | |
This is a good example of a partial with a small, explicit interface.
An Alert Partial
⧉
1 2 3 | |
Usage:
⧉
1 | |
The fragment receives only the values it needs.
Good Partial Design
A useful included template usually has:
- one clear purpose
- a small number of expected variables
- predictable markup
- little or no hidden business logic
- no unnecessary database access
- a descriptive filename
For example:
⧉
1 | |
is clearer than:
⧉
1 | |
Keep Business Logic Out of Includes
Django templates intentionally provide limited programming logic.
An included template should primarily handle presentation.
Good:
⧉
1 2 3 | |
Less desirable is trying to encode a large business workflow into nested template conditions.
If logic determines:
- who may access data
- whether an operation is allowed
- how prices are calculated
- which records should exist
that logic belongs in Python code.
Do Not Use Includes as a Permission Boundary
Suppose:
⧉
1 2 3 | |
This hides the button from ordinary users.
It does not secure the delete view.
The server must still enforce permission checks:
⧉
1 2 3 4 | |
Template visibility is presentation, not authorization.
Common Beginner Mistakes
Copying Markup Instead of Creating a Partial
If the same substantial HTML appears in several templates, consider an include.
Avoid maintaining several copies of:
⧉
1 2 3 | |
Using include for Page Inheritance
Do not replace a clear:
⧉
1 | |
structure with many large includes.
Use inheritance for overall layouts.
Expecting Blocks in Includes to Be Overridden
Blocks belong to inheritance.
An include is rendered independently.
Passing Too Much Context
This works:
⧉
1 | |
but the partial may silently depend on many parent variables.
For reusable components, consider:
⧉
1 | |
Using the Wrong Template Path
Use the configured template name:
⧉
1 | |
not the physical filesystem path.
Forgetting Variable Names
If the partial expects:
⧉
1 | |
pass:
⧉
1 | |
Overusing Dynamic Template Names
This:
⧉
1 | |
can be useful, but it is harder to search and reason about than a fixed template path.
Use dynamic includes when the flexibility is actually needed.
Creating Extremely Configurable Partials
A partial with many flags can become harder to use than duplicated simple markup.
Keep the interface small.
Ignoring Database Queries During Rendering
A partial may access related model data and cause extra queries.
Optimize the queryset in the view.
Putting Business Rules in Template Partials
Templates should present results, not become the main location for business decisions.
Using Includes for Security
Hiding a button does not prevent direct requests to the underlying view.
Permissions belong on the server.
Testing Included Templates
Most include behavior can be tested through the view that renders the complete page.
For example:
⧉
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | |
This checks the output users actually receive.
Testing a Partial Directly
For an isolated template test:
⧉
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | |
Direct partial tests can be useful for fragments containing meaningful presentation logic.
Do not test every trivial piece of HTML simply because it is included.
Debugging Includes
When an include does not behave as expected, check:
⧉
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | |
For context problems, temporarily rendering a variable can help:
⧉
1 | |
or:
⧉
1 | |
If it renders empty, check where the value should come from.
Recommended Include Style
For reusable application fragments, a good default is:
⧉
1 | |
This communicates:
⧉
1 2 3 4 5 6 7 8 | |
For simple shared fragments that naturally depend on standard context, a plain include may be fine:
⧉
1 | |
Use the form that makes the dependency easiest to understand.
When to Use include
Use {% include %} when:
- markup appears in several templates
- a large page can be divided into clear visual sections
- a repeated object needs a reusable card or row
- several pages share the same pagination
- forms use a repeated field layout
- navigation or messages should live in one place
- the fragment needs only template-level presentation logic
Examples:
⧉
1 2 3 4 5 6 7 8 9 | |
When Not to Use include
An include may not be appropriate when:
- you need page-level inheritance
- the fragment needs substantial Python logic
- the markup is used only once and extracting it reduces clarity
- the component requires many configuration flags
- the content requires its own HTTP endpoint
- the abstraction makes performance harder to understand
Use include when it reduces complexity, not simply to create more files.
Recommended Mental Model
Think of an included template as a small rendering function.
Conceptually:
⧉
1 2 3 4 5 | |
In Django syntax:
⧉
1 | |
The partial receives data and produces markup.
This mental model encourages small and predictable fragments.
Mini Reference
⧉
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | |
Basic include:
⧉
1 | |
Include inside a loop:
⧉
1 2 3 | |
Dynamic include:
⧉
1 | |
Typical structure:
⧉
1 2 3 4 5 6 7 8 | |
Conclusion
Django’s {% include %} template tag provides a simple way to reuse rendered HTML across templates.
The basic pattern is:
⧉
1 | |
The included template receives the current context by default.
Specific values can be passed with:
⧉
1 | |
and the fragment can be isolated from the surrounding context with:
⧉
1 | |
The most important ideas are:
includerenders another template inside the current one- included templates normally receive the current context
withpasses explicit valuesonlylimits the available context- includes work especially well for cards, navigation, pagination, messages, and other reusable fragments
- template inheritance and template inclusion solve different problems
- included templates should focus on presentation
- permissions and business rules still belong in Python
- related-object access inside partials can affect database performance
- reusable fragments should remain small and predictable
For most Django applications, the best place to start is simple:
⧉
1 | |
It removes duplicated markup while keeping the parent template easy to read and the reusable fragment easy to understand.
Join the Newsletter
Practical insights on Django, backend systems, deployment, architecture, and real-world development — delivered without noise.
Get updates when new guides, learning paths, cheat sheets, and field notes are published.
No spam. Unsubscribe anytime.
There is no third-party involved so don't worry - we won't share your details with anyone.