CodeOath
← All posts
Python70 min total · 18 parts

Django Fundamentals: MVT Architecture, the ORM, and Middleware

Contents — Part 11 of 18: Templates and the Template Language
Part 11 of 18 · ~1 min

Templates and the Template Language

{% extends "base.html" %}

{% block content %}
  <h1>Orders</h1>
  <ul>
    {% for order in orders %}
      <li>{{ order.customer.name }} — {{ order.total|floatformat:2 }}</li>
    {% empty %}
      <li>No orders yet.</li>
    {% endfor %}
  </ul>

  {% if user.is_authenticated %}
    <p>Welcome, {{ user.username }}</p>
  {% endif %}
{% endblock %}

Django's template language is deliberately limited — no arbitrary Python expressions, no assignment inside a template — as a design choice to keep business logic out of templates and in views, where it's testable. {{ order.customer.name }} looks like attribute access because it's actually more general than that: the . operator tries, in order, dictionary lookup, attribute lookup, list-index lookup, and finally calling it as a zero-argument method — whichever succeeds first.

Template inheritance and includes

{% extends %} (one base layout, overridden per-page blocks) and {% include %} (embed one template's rendered output verbatim into another) solve two different reuse problems: extends is for "every page shares this overall structure," include is for "this exact fragment (a card, a nav item) is reused as-is in several unrelated places."

Filters, and autoescaping

{{ order.total|floatformat:2 }}   {# formats a number to 2 decimal places #}
{{ comment.body|linebreaks }}     {# converts newlines to <p>/<br> tags #}
{{ user_input }}                  {# auto-escaped by default — safe against XSS #}
{{ trusted_html|safe }}            {# opts OUT of escaping — only for content you trust #}

Django auto-escapes every variable by default — <script> typed into a text field renders as the literal text &lt;script&gt;, not an executed tag. |safe explicitly disables that protection for one value, which is exactly why it should only ever be applied to content that's been through some other form of sanitization or is fully trusted (site-authored HTML, not raw user input).