Chapter 6: Django include Tag
include Tag: The {% include %} tag
Many beginners either:
- copy-paste the same HTML block (navbar, footer, question card, pagination, alert messages…) into 5–10 different templates → nightmare when you want to change one thing later
- or they overuse template inheritance ({% block %}) for things that are not really “replaceable sections” but “reusable snippets”
{% include %} solves exactly that second problem — it lets you pull in a small, independent template fragment anywhere you want.
Let’s learn it properly — step by step — like I’m sitting next to you, creating real reusable pieces together in your polls project.
1. The Simplest Possible {% include %}
Create a tiny reusable snippet:
File: polls/templates/polls/_vote_count_badge.html
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
{% if vote_count > 0 %} <span class="badge" style="background:#28a745; color:white; padding:4px 8px; border-radius:12px; font-size:0.85rem;"> {{ vote_count }} {{ vote_count|pluralize:"vote,votes" }} </span> {% else %} <span class="badge" style="background:#6c757d; color:white; padding:4px 8px; border-radius:12px; font-size:0.85rem;"> No votes yet </span> {% endif %} |
Now use it in any template:
|
0 1 2 3 4 5 6 7 8 9 10 11 |
<!-- in index.html or detail.html --> <h3>{{ question.question_text }}</h3> {% include "polls/_vote_count_badge.html" with vote_count=question.vote_count %} <p>Category: {{ question.category|title }}</p> |
→ The badge appears exactly the same way everywhere — change it once, everywhere updates.
2. Why the Underscore _ Prefix?
It’s a very strong convention (used by almost all Django developers):
- Files starting with _ are partials / fragments — not meant to be rendered alone
- They are included, never directly used in views
- Helps everyone instantly understand: “this is not a full page”
Common names:
- _question_card.html
- _pagination.html
- _alert_message.html
- _form_errors.html
- _footer.html (even if you also use block inheritance)
3. Passing Context with with (Very Important)
Without with → the included template gets exactly the same context as the parent.
With with → you can rename or add variables:
|
0 1 2 3 4 5 6 |
{% include "polls/_vote_count_badge.html" with vote_count=question.vote_count only %} |
The only keyword is very powerful:
- only → included template gets only the variables you pass in with
- No access to parent context (safer, cleaner, avoids bugs)
Real example — showing choices with question number:
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
{% for question in latest_questions %} <h3>{{ question.question_text }}</h3> {% for choice in question.choices.all %} {% include "polls/_choice_line.html" with choice=choice question_number=forloop.parentloop.counter only %} {% endfor %} {% endfor %} |
And _choice_line.html:
|
0 1 2 3 4 5 6 7 8 9 10 11 |
<li> Question #{{ question_number }} — Choice {{ forloop.counter }}: {{ choice.choice_text }} ({{ choice.votes|pluralize:"vote,votes" }}) </li> |
→ Clean, no leakage of outer variables
4. Dynamic Include (Advanced but Very Useful)
You can include different partials based on condition:
|
0 1 2 3 4 5 6 7 8 9 10 |
{% if question.vote_count > 10 %} {% include "polls/_trending_badge.html" %} {% else %} {% include "polls/_normal_badge.html" %} {% endif %} |
Or even variable-based:
|
0 1 2 3 4 5 6 |
{% include "polls/_" badge_type ".html" %} |
(though most teams avoid this — too magic)
5. {% include %} with with and Context Modifiers
|
0 1 2 3 4 5 6 7 8 9 10 11 |
{% include "polls/_user_info.html" with user=request.user show_avatar=True size="small" only %} |
→ Very clean way to reuse user avatar + name + role block everywhere
6. Common Real-Life Use Cases in 2026 Projects
-
Reusable cards / list items
_question_card.html → used in index, search results, dashboard
-
Pagination snippet
_pagination.html → used in every list view
-
Form error/success messages
_form_messages.html → include after every POST form
-
Alert banners
_alert.html → show site-wide announcements
-
Loading spinner / skeleton loader
_skeleton_loader.html → during AJAX loads
-
Admin-style action buttons
_admin_actions.html → edit/delete links (when shown on frontend)
7. Common Beginner Mistakes & Fixes
| Mistake | Symptom / Error | Correct way |
|---|---|---|
| {% include “polls/_badge.html” %} → 404 | Wrong path | Path is relative to templates/ root → polls/_badge.html |
| Variables not available in included file | Forgot with or only | Use with var=… only when you want isolation |
| Included file shows parent variables unexpectedly | No only keyword | Add only to prevent context leakage |
| {% include %} before {% extends %} | SyntaxError | extends must be first tag |
| Circular includes (file A includes B, B includes A) | Recursion error | Avoid — refactor to common partial |
Your Quick Practice Task (Do This Right Now)
-
Create polls/templates/polls/_vote_count_badge.html (copy the snippet above)
-
In index.html or detail.html, replace any vote display with:
HTML0123456{% include "polls/_vote_count_badge.html" with vote_count=question.vote_count only %} -
Create another partial _question_meta.html:
HTML0123456789<p class="meta">Category: {{ category|title }} •Published {{ pub_date|timesince }} ago</p>Include it:
HTML0123456{% include "polls/_question_meta.html" with category=question.category pub_date=question.pub_date only %} -
Try commenting one include with {% comment %} → see it disappear
Tell me what you want next:
- Which part of {% include %} feels confusing? (with/only? path? naming?)
- Want to see how to include from another app ({% include “blog/_post_card.html” %})
- Ready to learn {% with %} tag (local variable scope)?
- Or want more partial examples (pagination, alerts, form fields)?
- Or finally ready for Django Forms + Voting + POST + F()?
You’re now writing clean, reusable, professional templates — this {% include %} habit alone will save you days of work later.
Keep going — you’re doing really well! 🚀🇮🇳
