Chapter 2: Django Template Tags

Template tags — everything that lives inside {% %}

Many people learn {{ variable }} first and think “okay I can print stuff”, but real Django power comes from the tags. They control logic, loops, inheritance, loading extras, URL reversing, filters registration, etc.

Today I want to teach you template tags like a senior sitting next to you — not just listing them, but showing when, why, how and common beginner traps for each important one.

We’ll use your existing polls project as playground.

1. The Absolute Most Important Tag: {% extends %}

Almost every real template starts with this.

HTML
  • Tells Django: “use base.html as parent, I only want to fill some blocks”
  • Must be the very first tag in the file (no spaces or text before it)
  • Common beginner mistake → putting HTML or comments before it → breaks everything

Next lines are usually:

HTML

2. {% block %} + {{ block.super }} (the inheritance magic)

In child template:

HTML

In parent base.html:

HTML

→ Child can append to parent block (very useful for CSS/JS)

3. {% load %} – Bring extra tags/filters

You write this near the top (after {% extends %} if present)

HTML

Common ones you will use every week:

  • {% load static %} → for CSS/JS/images
  • {% load i18n %} → translations
  • {% load humanize %} → nicer numbers (1,234 → 1,234)
  • {% load cache %} → fragment caching

4. {% url %} – Never hardcode links again

HTML
  • First part = app_name:view_name
  • Then keyword arguments matching the <slug:slug> / <int:pk> in path()
  • Never write /polls/{{ question.slug }}/ — it breaks when URL pattern changes

5. {% for %} + {% empty %} + loop variables

HTML

Useful loop variables:

  • forloop.counter → 1, 2, 3…
  • forloop.counter0 → 0, 1, 2…
  • forloop.first / forloop.last → True/False
  • forloop.revcounter → countdown from end
  • forloop.parentloop.counter → nested loops

6. {% if %}, {% elif %}, {% else %}

HTML

Can also test:

  • {% if not question.choices.exists %}
  • {% if question.vote_count > 10 %}
  • {% if user.is_authenticated %}
  • {% if perms.polls.add_question %}

7. {% include %} – Reuse small template pieces

Create polls/templates/polls/_question_card.html:

HTML

Then in index.html:

HTML

→ Very clean when cards are repeated in multiple places

8. {% static %} – Link to CSS/JS/images

HTML

You need to run python manage.py collectstatic in production.

9. {% verbatim %} – Escape Django syntax (rare but useful)

HTML

Useful when showing Django code examples in your own docs page.

10. {% spaceless %} – Remove extra whitespace (sometimes needed)

HTML

→ Removes newlines between tags → cleaner HTML

Quick Reference Table – Tags You’ll Use Every Day

Tag Purpose Most common use-case
{% extends %} Inherit from parent template Every page except base.html
{% block %} Define replaceable section title, content, extra_head, extra_js
{% load %} Load custom tags/filters static, humanize, your own poll_extras
{% url %} Reverse URL every and form action
{% for %} + {% empty %} Loop over queryset/list listing questions, choices, comments
{% if %} / {% elif %} Conditional rendering show/hide elements, active/inactive badges
{% include %} Insert another template fragment reusable cards, navbars, footers
{% static %} Link to static files CSS, JS, images
{% csrf_token %} Security for POST forms inside every <form method=”post”>

Your Quick Practice Task (Do This Right Now)

Open your polls/templates/polls/index.html and try to add these:

  1. {% url ‘polls:detail’ slug=question.slug %} in the link
  2. {{ question.pub_date|date:”l, d F Y” }} (weekday + date)
  3. {{ question.vote_count|pluralize:”vote,votes” }}
  4. {% if forloop.first %}<strong>Featured:</strong>{% endif %}
  5. {% load humanize %} + {{ question.vote_count|intcomma }}

Tell me what you want next:

  • Which tag is still confusing? (url? block? include?)
  • Want more filter examples (especially date & number formatting)?
  • Want to write your first custom template filter together?
  • Or ready for the next big topic: Django Forms + Voting + POST + F()

You’re getting really strong with templates now — this is where the frontend starts to feel alive.

Keep going — you’re doing fantastic! 🚀🇮🇳

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *