Python Flask¶
Python Flask is een web framework in Python. Een framework is een verzameling van code die je helpt om sneller en gemakkelijker software te maken. Flask helpt je specifiek om een webserver te maken.
Wat is een webserver?¶
Een webserver is een stuk software dat luistert naar verzoeken (requests) van webbrowsers en andere applicaties, en daarop reageert met antwoorden (responses).
Wanneer jij in je browser naar http://localhost/ gaat, stuurt je browser een verzoek naar de webserver.
De webserver verwerkt dit verzoek en stuurt een antwoord terug, bijvoorbeeld een HTML-pagina of JSON-data.
Flask maakt het mogelijk om zo’n webserver te bouwen met Python. In plaats van dat je alle technische details van HTTP (het protocol dat webbrowsers en servers gebruiken) zelf moet programmeren, geeft Flask je handige functies waarmee je snel een werkende webserver kunt maken.
Wat is een endpoint?¶
Een endpoint is een specifieke locatie op je webserver waar je naartoe kunt gaan met een URL. Je kunt het zien als een deur in een gebouw: elke deur heeft een adres (de URL) en wanneer je die deur opent (een verzoek stuurt), gebeurt er iets (de server voert code uit en stuurt een antwoord terug).
In Flask maak je een endpoint met de @app.route() decorator. Een decorator is een speciale Python-functie
die boven een andere functie wordt gezet om die functie extra functionaliteit te geven.
Hier is een voorbeeld van een hello-world endpoint:
In dit voorbeeld:
/hellois het pad (path) van het endpointhello()is de functie die wordt uitgevoerd wanneer iemand naar dit endpoint gaat- De functie retourneert
'Hello, World!', wat de server terugstuurt naar de browser
Voeg deze code toe aan je app.py file en navigeer naar http://localhost/hello in je browser.
Als alles goed is gegaan, zou je de tekst ‘Hello, World!’ in je browser moeten zien.
Waarom geef je HTTP-methodes mee aan endpoints?¶
HTTP (HyperText Transfer Protocol) kent verschillende methodes die aangeven wat voor soort actie je wilt uitvoeren. De meest gebruikte methodes zijn:
| Methode | Betekenis | Wanneer gebruik je het? |
|---|---|---|
GET |
Ophalen | Wanneer je data wilt ophalen of een pagina wilt bekijken |
POST |
Versturen | Wanneer je data naar de server wilt sturen (bijvoorbeeld een formulier) |
PUT |
Vervangen | Wanneer je bestaande data volledig wilt vervangen |
DELETE |
Verwijderen | Wanneer je data wilt verwijderen |
Waarom is dit belangrijk?
Stel je voor dat je een endpoint hebt waar gebruikers hun profiel kunnen bekijken Γ©n kunnen aanpassen. Zonder HTTP-methodes zou je twee verschillende endpoints moeten maken:
/profiel/bekijken/profiel/aanpassen
Met HTTP-methodes kun je hetzelfde endpoint gebruiken, maar verschillende acties uitvoeren afhankelijk van de methode:
@app.route('/profiel', methods=['GET'])
def profiel_bekijken():
# Toon het profiel
return render_template('profiel.html')
@app.route('/profiel', methods=['POST'])
def profiel_aanpassen():
# Sla de wijzigingen op
return 'Profiel aangepast!'
Dit maakt je code overzichtelijker en volgt de standaard manier waarop het web werkt.
Standaard gebruikt Flask GET als je geen methode opgeeft, maar het is goed om expliciet te zijn over wat je endpoint doet.
De static en templates mappen¶
Flask heeft een speciale structuur voor het organiseren van je bestanden. Twee belangrijke mappen zijn static en templates.
De templates map¶
De templates map bevat HTML-templates. Een template is een HTML-bestand met speciale plaatshouders waar je dynamische data in kunt stoppen.
Waarom templates? In plaats van dat je HTML-code als een lange string in je Python-code schrijft (wat onoverzichtelijk wordt), schrijf je gewone HTML-bestanden en gebruik je Flask’s template-engine om data erin te stoppen.
Voorbeeld van een template (templates/profiel.html):
<!DOCTYPE html>
<html>
<head>
<title>Profiel van {{ naam }}</title>
</head>
<body>
<h1>Welkom, {{ naam }}!</h1>
<p>Je bent {{ leeftijd }} jaar oud.</p>
</body>
</html>
In je Flask-code gebruik je deze template zo:
@app.route('/profiel')
def profiel():
return render_template('profiel.html', naam='Sam', leeftijd=19)
Flask zoekt automatisch in de templates map naar het bestand profiel.html en vervangt {{ naam }} en {{ leeftijd }} met de waarden die je meegeeft.
De static map¶
De static map bevat statische bestanden: bestanden die niet veranderen en direct naar de browser worden gestuurd zonder dat Flask ze hoeft te verwerken. Dit zijn bijvoorbeeld:
- CSS-bestanden (voor styling)
- JavaScript-bestanden (voor interactiviteit)
- Afbeeldingen (PNG, JPG, SVG, etc.)
- Fonts
Waarom een aparte map? Flask behandelt bestanden in de static map anders dan templates. Statische bestanden worden direct geserveerd zonder dat Flask ze door een template-engine hoeft te halen, wat sneller is.
In je HTML-templates verwijs je naar statische bestanden met de url_for() functie:
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
<img src="{{ url_for('static', filename='logo.png') }}" alt="Logo">
De structuur ziet er dan zo uit:
jouw-project/
βββ app.py
βββ templates/
β βββ profiel.html
βββ static/
βββ style.css
βββ logo.png
Wat bevat de URL van een endpoint?¶
Een URL (Uniform Resource Locator) is het adres dat je in je browser intypt. Laten we een URL ontleden:
| Deel | Naam | Uitleg | Voorbeeld |
|---|---|---|---|
http:// |
Protocol | Geeft aan welk protocol wordt gebruikt | http:// of https:// |
localhost |
Hostname | De naam van de server (localhost = je eigen computer) | localhost of example.com |
/profiel |
Pad (Path) | Het pad naar het endpoint | /profiel, /hello, /api/data |
?naam=Sam&leeftijd=19 |
Query parameters | Extra informatie die je meegeeft (optioneel) | ?naam=Sam&leeftijd=19 |
In Flask kun je query parameters ophalen met request.args:
from flask import request
@app.route('/profiel')
def profiel():
naam = request.args.get('naam', 'Onbekend') # 'Onbekend' is de standaardwaarde
leeftijd = request.args.get('leeftijd', '0')
return f'Naam: {naam}, Leeftijd: {leeftijd}'
Je kunt ook variabelen direct in het pad opnemen:
Dan zou de URL zijn: http://localhost/profiel/Sam
Je eigen endpoint aanmaken¶
Nu je begrijpt hoe endpoints werken, kun je je eigen endpoint maken. Volg deze stappen:
-
Open je Flask-applicatiebestand (meestal
app.py) -
Voeg een nieuwe route toe met de
@app.route()decorator:
- Test je endpoint door naar
http://localhost/mijn-endpointte gaan in je browser
Je kunt ook complexere endpoints maken:
@app.route('/bereken/<getal1>/<getal2>')
def bereken(getal1, getal2):
som = int(getal1) + int(getal2)
return f'De som van {getal1} en {getal2} is {som}'
Of een endpoint met een POST-methode:
@app.route('/verstuur', methods=['POST'])
def verstuur():
data = request.form.get('bericht')
return f'Je hebt verstuurd: {data}'
Belangrijk: Vergeet niet om from flask import Flask, request bovenaan je bestand te hebben staan als je request gebruikt!
Debuggen: output bekijken in de Docker container¶
Wanneer je code niet werkt zoals verwacht, is het belangrijk om te kunnen zien wat er gebeurt. Flask print informatie naar de console (de terminal), en in een Docker-omgeving zie je deze output in de Docker container logs.
Output bekijken in Docker Desktop¶
- Open Docker Desktop
- Zoek je Flask container in de lijst van draaiende containers
- Klik op de container om de details te zien
- Klik op het “Logs” tabblad om de output te bekijken
Hier zie je: - Wanneer de server start - Foutmeldingen (errors) - Print-statements die je in je code hebt staan - HTTP-requests die binnenkomen (als Flask in debug mode staat)
Print-statements gebruiken¶
In je Flask-code kun je print() gebruiken om informatie te loggen:
@app.route('/test')
def test():
print('Dit endpoint is aangeroepen!')
naam = 'Sam'
print(f'De naam is: {naam}')
return 'Check de Docker logs!'
Wanneer je nu naar /test gaat, zie je deze berichten in de Docker container logs.
Veelvoorkomende problemen en oplossingen¶
| Probleem | Mogelijke oorzaak | Oplossing |
|---|---|---|
| “404 Not Found” | Endpoint bestaat niet of pad is verkeerd | Check of de route correct is gespeld |
| “Method Not Allowed” | Verkeerde HTTP-methode gebruikt | Voeg de juiste methode toe: methods=['POST'] |
| Template niet gevonden | Bestand staat niet in templates map |
Zorg dat het bestand in de templates map staat |
| Statisch bestand niet gevonden | Verkeerd pad gebruikt | Gebruik url_for('static', filename='...') |
Door regelmatig de Docker logs te bekijken, leer je snel wat er misgaat en kun je je code stap voor stap verbeteren!