Werken met templates in Django

Werken met templates in Django

5 september 2024
Erwin Matijsen
Geplaatst in Tutorial
Onderdeel van Werken met Django


HTML en CSS

Deze tutorial veronderstelt enige basiskennis van HTML en CSS. Heb je dit niet, kijk dan bijvoorbeeld eens op MDN Web Docs. Voor nu is echt alleen de absolute basis nodig!

In Webapplicaties maken met Django - Introductie heb je geleerd wat Django is en heb je een eerste eenvoudig project aangemaakt. In dat project heb je gezien hoe de request / response cyclus werkt.

Je hebt een view gemaakt (home genaamd), waarin je een eenvoudige request / response cyclus hebt geïmplementeerd. Een view is een functie of een klasse dat een HttpRequest-object ontvang en een HttpResponse-object teruggeeft. In de view kun je van alles doen. De home-view ziet er zo uit:

tracker/views.py
from django.http import HttpResponse

def home(request):
    return HttpResponse("Welkom bij AutoTracker!")

De response is niet zo spannend: een witte pagina met de tekst "Welkom bij AutoTracker!"

In deze tutorial ga je die response uitbreiden en ervoor zorgen dat de pagina er al als een echte website (webapplicatie) uitziet. Dus: een menu, een middendeel en een footer. Omdat dit geen tutorial over het opmaken van pagina's is, houd je de opmaak eenvoudig.

Templates

Je kunt natuurlijk zoiets doen om een echte pagina als response terug te geven:

from django.http import HttpResponse

pagina = """
<!DOCTYPE html>
<html lang="nl">
<head>
    <title>AutoTracker</title>
</head>
<body>
    <nav>
      <ul>
        <li><a href="/"><strong>AutoTracker</strong></li></a>
      </ul>
    </nav>

    <main class="container">
        <h1>Welkom bij AutoTracker!</h1>
    </main>

    <footer>
        <small>© 2024 AutoTracker.</small>
    </footer>
</body>
</html>
"""


def home(request):
    return HttpResponse(pagina)

En dat zou werken. Je zou een eenvoudige HTML-pagina als resultaat krijgen. Maar dit is niet erg werkbaar. Wat als er een tweede view bijkomt, bijvoorbeeld één met het overzicht van je auto's die je hebt? Dan zou je een groot deel van de HTML-code moeten herhalen. De header, het menu, de div waarin de inhoud komt (main), de footer...

Als je dan een wijziging wilt aanbrengen in de structuur - je wilt bijvoorbeeld een submenu toevoegen - dan moet je alle views langs om dit erin te zetten.

Gelukkig kan dit eenvoudiger, en wel met templates.

Wat zijn templates?

Een template is een herbruikbaar HTML-bestand waarmee je de structuur en opmaak van een pagina bepaalt. In het template kun je op dynamische wijze inhoud toevoegen, maar dat is iets voor later. Voor nu is het vooral belangrijk om te onthouden dat een template dubbel werk voorkomt.

Om een template te maken, maak je eerst een map genaamd templates in een app-folder, in dit geval in tracker. Standaard zoekt Django namelijk naar templates in mappen genaamd templates in alle app-folders.

In templates plaats je twee bestanden: base.html en index.html. Om eenvoudig stijl en structuur aan je webpagina's te geven kun je gebruik maken van Pico CSS. Download pico, pak het uit en plaats de map css in tracker/static/css.

Je mappenstructuur ziet er nu zo uit:

autotracker/
├── conf/
├── tracker/
│   ├── migrations/
│   ├── static/
│   │   ├── css
│   ├── templates/
│       ├── base.html
│       ├── index.html
│   ├── ...
├── manage.py
└── requirements.txt

Het bestand base.html zal als basis dienen voor al je toekomstige templates. Hierin plaats je de basisstructuur van je webapplicatie. Een eenvoudige structuur voldoet voor nu.

<!DOCTYPE html>
<html lang="nl" data-theme="light">
<head>
    {% load static %}
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>AutoTracker</title>
    <link rel="stylesheet" href="{% static 'css/pico.min.css' %}">
</head>
<body>
    <header class="container">
        <nav>
          <ul>
            <li><strong>AutoTracker</strong></li>
          </ul>
        </nav>
    </header>

    <main class="container">
        <h1>Welkom bij AutoTracker!</h1>
    </main>

    <footer class="container">
        <small>© 2024 AutoTracker.</small>
    </footer>
</body>
</html>

Je ziet dat het bijna hetzelfde is als het eerdere voorbeeld, waar je de HTML direct in de view plaatste. Er zijn twee belangrijke verschillen. Ten eerste zie je vlak onder <head> iets nieuws staan: {% load static %}. Dit is geen HTML, maar onderdeel van de template-taal van Django. Hiermee bereid je voor dat je statische bestanden zoals CSS eenvoudig kunt inladen.

Dit inladen van CSS zie je op de regel onder <title. Het begint als een reguliere manier om een CSS-bestand in te laten. Alleen de href verwijst niet naar een relatief of absoluut pad, maar naar {% static 'css/pico.min.css' %}. Wat dit doet, is dat het css/pico.min.css toevoegt aan de static-URL. Met de standaard-instellingen is dit de url /static/. Als de template later wordt omgezet in echte HTML, staat er dus eigenlijk: /static/css/pico.min.css.

Templates gebruiken

Je hebt nu een basis-template gemaakt, welke gaat dienen als basis voor al je pagina's. Moet er nu iets in het menu gewijzigd worden, dan kun je dat in de template doen, en alle pagina's die deze template gebruiken zullen de wijziging ook doorvoeren.

Maar hoe gebruik je dit template nu?

De eerste stap is in index.html, welke je eerder hebt aangemaakt, één regel te plaatsen:

{% extends "base.html" %}

Hiermee zeg je eigenlijk: index.html bouwt verder op base.html. Zo kun je een basis gebruiken (base.html) en toch per pagina unieke elementen toevoegen. Voor nu hoeft dit nog niet, dus feitelijk zijn index.html en base. html nog hetzelfde.

De tweede stap is de home-view aan te passen. Eerst zie je nog de oude code:

tracker/views.py (OUD)
from django.http import HttpResponse

def home(request):
    return HttpResponse("Welkom bij AutoTracker!")

Vervang dit nu door de nieuwe code:

tracker/views.py (NIEUW)
from django.shortcuts import render

def home(request):
    return render(request, "index.html")

Importeer render, dit is een handige functie waarmee je een template kunt 'renderen' en een HttpResponse teruggeeft. In plaats van direct een HttpResponse terug te geven, geef je nu dus de render-functie terug, met als eerste argument request en als tweede argument de template die je wilt gebruiken (index.html).

Herlaad nu je pagina. Als het goed is zie je nu een eenvoudige, maar opgemaakte pagina:

Je nieuwe homepage

Een tweede pagina

Voor één pagina lijkt het maken en gebruiken van een template misschien veel werk voor weinig voordeel. Het voordeel wordt echter al snel duidelijk als je nog een pagina toevoegt.

Om dit aan te tonen is het eerst nodig om base.html aan te passen. Op de plaats waar "Welkom bij AutoTracker!" staat, plaats je nu een zogenaamd block.

tracker/templates/base.html
...
    <main class="container">
        {% block main %}{% endblock main %}
    </main>
...

Je hebt een block toegevoegd met de naam main. In dit blok kun je in templates die base.html als basis gebruiken, inhoud plaatsen.

In index.html plaats je nu het volgende:

tracker/templates/index.html
{% extends "base.html" %}

{% block main %}
    <h1>Welkom bij AutoTracker!</h1>
{% endblock main %}

Je gebruikt nu weer block om de inhoud voor index.html toe te voegen. Maak op dezelfde plaats als index.html een tweede HTML-bestand en noem dit overview.html. Hierin plaats je grotendeels hetzelfde als in index.html, maar met eigen inhoud:

tracker/templates/overview.html
{% extends "base.html" %}

{% block main %}
    <h1>Overview</h1>
{% endblock main %}

Je ziet dat je nu twee pagina's hebt gemaakt, die allebei voortborduren op base.html, en met minimale aanpassingen hun eigen inhoud laten zien.

Als laatste stap zijn nu nog een nieuwe view en URL nodig.

Lees nog eens de introductie om te kijken hoe je views en URL's maakt.

Voeg in views.py het volgende toe:

tracker/views.py
from django.shortcuts import render

...

def overview(request):
    return render(request, "overview.html")

En in conf/urls.py voeg je de url toe:

tracker/views.py
...

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', home, name='home'),  # Vergeet niet de komma hier te plaatsen
    path('overview', overview, name='overview')
]

Vergeet niet overview te importeren uit tracker.views.

Herstart nu de server en herlaad de pagina. Als het goed is zie je nog steeds "Welkom bij AutoTracker!" op de homepage. Typ je nu als url in localhost:8000/overview, dan zie je als het goed is ook een netjes opgemaakte pagina met een eigen inhoud, namelijk "Overview".

Menu toevoegen

De laatste stap is om het menu te wijzigen in base.html. In conf/urls.py heb je de url's een naam gegeven. Deze naam kun je nu gebruiken in je templates. Verander het stukje menu in base.html naar het volgende:

tracker/templates/base.html
...

<header class="container">
    <nav>
      <ul>
        <li><a href="{% url 'home' %}"><strong>AutoTracker</strong></a></li>
          <li><a href="{% url 'overview' %}">Overzicht</a></li>
      </ul>
    </nav>
</header>

...

In de links voeg je geen hardcoded URL's toe, maar gebruik je de {% url '<naam>' %}-syntax. Django zal hierdoor bij het omzetten van de template naar HTML de url die bij de naam hoort invoegen. Besluit je nu om je url's te wijzigen, dan kun je dat in urls.py doen in plaats van in je templates.

Template tags

In je template heb je nu al een paar keer {% ... %} gebruikt. Eerst om je CSS in te laden, later om een block te maken en te gebruiken en nu tot slot om eenvoudig je url's te gebruiken.

Deze construcies heten template tags, en zijn een belangrijk onderdeel van templates. Je kunt er je templates dynamisch mee maken en je voorkomt handmatig werk. De complete lijst van template tags is te vinden in de Django documentatie.

Je hebt nu twee pagina's met dezelfde basis, maar toch ieder hun eigen inhoud. Ondanks dat het heel eenvoudig is, merk je nu al het voordeel van het gebruiken van een template. De basis voor elke pagina haal je uit base.html, en per pagina voeg je alleen dat toe wat verschilt per pagina.

Verdere stappen

In deze tutorial heb je de basis van het werken met templates in Django geleerd. Templates zijn een krachtig hulpmiddel bij het maken van dynamische, complexe webapplicaties. Nu heb je twee pagina's gemaakt met een eenvoudige structuur en waar alleen de titels per pagina wisselen. In vervolg-tutorials leer je hoe je meer dynamische inhoud aan pagina's kunt toevoegen.

Over de auteur


Erwin Matijsen

Erwin Matijsen

Erwin is de oprichter van python-cursus.nl. In allerlei rollen heeft hij Python ingezet, van het eenvoudiger maken van zijn werk tot het opleveren van complete (web)applicaties. Met vrouw en kinderen woont hij in Havelte (Drenthe), midden in de prachtige natuur. Daar wandelt hij graag, zeker ook omdat de beste ingevingen tijdens een wandeling - weg van de computer - lijken te komen.


Contact

Training volgen?

Heb je behoefte aan een in-person training voor jezelf of je team? Dat kan! Laat je gegevens achter en dan nemen we zo snel mogelijk contact met je op de mogelijkheden te bespreken.


Contact

Vragen, opmerkingen?

Heb je vragen, opmerkingen, suggesties of tips naar aanleiding van deze blog? Neem dan contact met ons op, of laat het weten via Mastodon of LinkedIN.