Context toevoegen aan Django templates

Context toevoegen aan Django templates

5 januari 2025
Erwin Matijsen
Geplaatst in Tutorial
Onderdeel van Werken met Django


In de vorige tutorial leerde je over de basis van templates in Django. In deze tutorial ga je een stap verder en ga je context toevoegen. De context is een dict die je mee kunt geven aan een template. Hiermee kun je allerlei gegevens beschikbaar maken in je template, bijvoorbeeld een lijst om over te itereren.

Aan het eind van deze tutorial heb je de overview-template uit de vorige tutorial uitgebreid met een lijst met auto's die je (al dan niet fictief) in je bezit hebt, en met je naam. Dat ziet er ongeveer zo uit:

Het eindresultaat van deze tutorial

Open je autotracker-project en activeer de venv.

shell
cd ~/projects/autotracker
source .venv/bin/activate  # .venv\Scripts\activate.bat voor Windows

Auto objecten maken

Een context is in de context (ha ha) van templates een dict met objecten. Dat kan eigenlijk van alles zijn, en het hangt helemaal van je applicatie af wat een logische context is. In het geval van AutoTracker is een belangrijk object natuurlijk de auto. Om de context te demonstreren, ga je de overview-pagina uitbreiden met auto's die je momenteel in je bezit hebt.

Dat ga je eerst nog op een statische manier doen. Later in deze reeks zul je gaan werken met een database waarin je auto's zijn opgeslagen. Maar voor nu volstaat het om enkele objecten handmatig aan te maken.

Dat kan op verschillende manieren. Gebruik voor nu een dataclass. Als je nog niet bekend met dataclasses, een dataclass is een speciale klasse, waarmee je op vereenvoudigde wijze gegevens kunt opslaan. Ideaal dus als je vooral met gegevens wilt werken, en niet zozeer met logica.

Een dataclass voor een auto maak je als volgt aan:

models.py
from dataclasses import dataclass

@dataclass
class Car:
    name: str
    purchase_price: int
    purchase_year: int
    construction_year: int
    fuel_type: str
    km_at_purchase: int

Je ziet dat je klasse-attributen en type hints gebruikt om een dataclass op te bouwen. Het is een verkorte manier voor:

class Car:
   def __init__(self, name: str, purchase_price: int, purchase_year: int, 
                construction_year: int, fuel_type: str, km_at_purchase: int):
       self.name = name
       self.purchase_price = purchase_price 
       self.purchase_year = purchase_year
       self.construction_year = construction_year
       self.fuel_type = fuel_type
       self.km_at_purchase = km_at_purchase

In de Basiscursus Python lees je nog eens over het werken met klassen. In Werken met Pythons Typesysteem en Type Hints lees je nog eens over het werken met types.

Plaats de Car-klasse in het bestand models.py, in de tracker-map. In latere tutorials leer je wat 'echte' models zijn en hoe je ermee werkt, voor nu volstaat deze dataclass.

De volgende stap is om een aantal auto's te maken. Je kunt je eigen auto('s) invoeren, maar je kunt er ook een paar bedenken. Maak er in elk geval meer dan één. Doe dit in de functie overview in tracker/views.py. Vergeet niet de Car-klasse te importeren.

views.py
from tracker.models import Car

def overview(request):

    leaf = Car(
        name="Nissan Leaf",
        purchase_price=12000,
        purchase_year=2024,
        construction_year=2018,
        fuel_type="Electric",
        km_at_purchase=90000
    )

    ford = Car(
        name="Ford Focus Wagon",
        purchase_price=10000,
        purchase_year=2023,
        construction_year=2018,
        fuel_type="Gas",
        km_at_purchase=120000
    )


    return render(request, "overview.html")

Auto's aan de context toevoegen

Je hebt nu een aantal auto's aangemaakt in de overview-functie, maar hiermee zijn ze nog niet beschikbaar in je templates. Daarvoor voeg je ze eerst toe als context. Een context is een eenvoudige dict met objecten, in dit geval de auto's. Het toevoegen van de context doe je in twee stappen.

Maak eerst een dict genaamd context aan, met als sleutel "cars" en als waarden een lijst met je zojuist aangemaakte auto's. Je hoéft deze dict overigens geen context te noemen, maar het is wel zo duidelijk om dat wel te doen.

Vervolgens geef je deze dict mee aan de render-functie.

views.py
from tracker.models import Car

def overview(request):

    leaf = Car(
        ...
    )

    ford = Car(
        ...
    )

    context = {
        "cars": [leaf, ford]
    }

    return render(request, "overview.html", context=context)

En dat is het! In je template is "cars" nu beschikbaar als variabele. Hoe dat werkt, zie je zo. Om te laten zien dat je van alles aan een context kunt toevoegen, kun je de dict nog met iets (willekeurigs) uitbreiden. Bijvoorbeeld je naam:

context = {
    "cars": [leaf, ford],
    "name": "Erwin Matijsen"
}

De context in een template gebruiken

Je hebt nu een context beschikbaar gemaakt aan je template. De sleutels van je dict worden beschikbaar als variabelen in je template. In dit geval heb je dus twee variabelen tot je beschikking in je overview-template: cars en name. Maar hoe gebruik je deze variabelen nu in je template?

Variabelen

Dit doe je op de eenvoudigste manier met de syntax voor variabelen: {{ <variabele> }}. Voeg aan overview.html bijvoorbeeld het volgende toe:

overview.html
{% extends "base.html" %}

{% block main %}
    <h1>Overzicht</h1>
    <hr/>

    <p>Hallo, {{ name }}. Dit zijn je auto's: </p>
    <p>{{ cars }}</p>

{% endblock main %}

Je ziet dat je {{ name }} en {{ cars }} kunt gebruiken. Herlaad de pagina, en je zult zien dat je de waarde ziet die je aan de context hebt toegevoegd met de sleutel name. Daar waar je {{ cars }} hebt toegevoegd, zie je een (niet zo mooie) lijst met je Car-objecten.

Gebruik van variabelen in een Django Template

Template tags

Dat werkt, maar is niet zo mooi natuurlijk. Het zou mooier zijn als je een nette lijst zag met de namen van de auto's en bijvoorbeeld het aanschafjaar erachter. Dit doe je met de for-template tag. Template tags heb je al eerder gebruikt, namelijk {% extends "base.html" %} en {% block main %}. Misschien herken je de syntax al voor de meeste template tags: {% ... %}.

De for-template tag is iets uitgebreider. Het werkt vergelijkbaar als een for-loop in Python. Verander je template naar het volgende:

overview.html
{% extends "base.html" %}

{% block main %}
    <h1>Overzicht</h1>
    <hr/>

    <p>Hallo, {{ name }}. Dit zijn je auto's: </p>

    <ol>
    {% for car in cars %}
        <li>{{ car.name }} ({{ car.purchase_year }})</li>
    {% endfor %}
    </ol>

{% endblock main %}

Je begint de for-loop met {% for item in items %} en eindigt het met {% endfor %}. Dit plaats je tussen de <ol>-tags. Voor elk item in de cars-lijst zul je nu een <li>-element toevoegen, met de naam van de auto en tussen haakjes het jaar van aanschaf. In elke loop heb je een variabele car tot je beschikking. Om deze aan te roepen, plaats je het weer tussen {{ en }}. Omdat elke car een object van het type Car is, kun je de verschillende attributen aanroepen met de punt-notatie. Dus bijvoorbeeld car.name voor de naam en car.purchase_year voor het jaar van aanschaf.

Je kunt nog een kleine verbetering doorvoeren. Want wat als je (nog) geen auto's hebt toegevoegd? Hiervoor gebruik je de {% if ... %}-template tag.

{% if cars %}
    <ol>
    {% for car in cars %}
        <li>{{ car.name }} ({{ car.purchase_year }})</li>    
    {% endfor %}
    </ol>
{% else %}
    <p>Je hebt nog geen auto's toegevoegd</p>
{% endif %}

Hiermee toets je eerst of er een variabele cars is (of dat hij in elk geval niet leeg is). Als dit zo is, dan maak je de lijst met de {% for ... %}-constructie. Is er geen lijst met auto's, dan toon je een alternatieve tekst.

Maak de lijst in de context-dict maar eens leeg en kijk wat er in je template gebeurt als je de pagina herlaadt.

Oefening

Probeer als oefening eens de lijst in de template uit te breiden met andere kenmerken van de auto's, zoals de kilometerstand bij aanschaf. Om het overzichtelijk te maken zou je het in een tabel kunnen plaatsen. Lees op MDN Web Docs hoe je een HTML tabel maakt.

Template filters

Naast template tags zijn er ook nog zogenaamde template filters. Met een template filter kun je waardes in een template wijzigen. Een simpel voorbeeld is de upper-filter, waarmee je een waarde omzet in kapitalen. Bijvoorbeeld de naam van je auto:

...
<li>{{ car.name|upper }} ({{ car.purchase_year }})</li>   
...

Je voegt |upper toe achter car.name. Een filter begint altijd met een |, gevolgd door de naam van het filter. Bij sommige filters is het ook nog mogelijk argumenten mee te geven, maar bij upper is dat niet het geval. Herlaad de pagina om te kijken of het werkt.

Conclusie

Je hebt gezien dat je op een eenvoudige manier je templates dynamisch kunt maken door een context toe te voegen. Een context is een dict met daarin items die je aan de template wilt toevoegen. Dit kan van alles zijn, van een eenvoudige str tot een uitgebreide lijst met complexe objecten.

Je roept een variabele in je template aan met {{ <variable> }}. Je kunt er ook over itereren met {% for ... %}. Dit zijn slechts de eerste stappen, met andere template tags en template filters is nog veel meer mogelijk. Maar de basis blijft gelijk. Zie de Django Documentatie voor meer template tags en template filters.

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.