Django Templates

Django templates generate dynamic HTML by mixing static markup with {{ }} variables and template tags that Django fills in at render time.

Rendering a Template from a View

The render() shortcut takes the request, a template name, and an optional context dictionary. It finds the template, fills in the context, and returns an HttpResponse - all in one call.

Example

from django.shortcuts import render

def home(request):
    context = {
        'page_title': 'Welcome',
        'visitor_count': 128,
    }
    return render(request, 'core/home.html', context)

Where Django Looks for Templates

With APP_DIRS enabled in the TEMPLATES setting (the default in a new project), Django searches for a templates/ folder inside each installed app. The convention is to nest templates one level deeper in a folder named after the app, so myapp/templates/myapp/home.html - this avoids two apps accidentally shadowing a template with the same file name.

Example

myapp/
    templates/
        myapp/
            home.html

<!-- myapp/templates/myapp/home.html -->
<!DOCTYPE html>
<html>
<head><title>{{ page_title }}</title></head>
<body>
    <h1>{{ page_title }}</h1>
    <p>Visitors so far: {{ visitor_count }}</p>
</body>
</html>

Variable Syntax: {{ }}

{{ variable }} outputs a value from the context. Dot notation walks through the value step by step, and Django tries each of the following lookups in order until one succeeds: dictionary key lookup, attribute lookup, list-index lookup, then a no-argument method call.

  • Dictionary lookup - {{ post.title }} tries post['title'] first
  • Attribute lookup - falls back to post.title as an object attribute
  • List-index lookup - {{ tags.0 }} returns tags[0]
  • Method call - {{ queryset.count }} calls queryset.count() with no arguments

Example

<p>Welcome back, {{ user.username }}</p>
<p>Latest post: {{ latest_post.title }}</p>
<p>First tag: {{ tags.0 }}</p>
<p>Total posts: {{ posts.count }}</p>
SyntaxLooks Up
{{ user.username }}Attribute username on the user object
{{ post.title }}Dictionary key or attribute named title
{{ items.0 }}Index 0 of the items list
{{ queryset.count }}Calls the count() method if one exists
Note: Chain dot lookups and pipe the result through the default filter so missing data never renders as an empty string: {{ user.profile.bio|default:'No bio yet' }}.

Exercise: Django Templates

What is the main purpose of Django's template system?