Skip to content
Programmeren in Python, leer de nieuwste technieken
Programmeren in PythonProgrammeren in Python
  • Home
  • Blog
  • Documentatie
  • Cursussen
  • Tools
    • Python Paste
Programmeren in PythonProgrammeren in Python
  • Home
  • Blog
  • Documentatie
  • Cursussen
  • Tools
    • Python Paste

Introductie

3
  • 1.1 Wat is Python?
  • 1.2 Python installatie
  • 1.3 PyCharm Installatie

Basisprogrammering

6
  • 2.1 Python Basis: Variabelen, Datatypes en Operatoren
  • 2.2 Python if else (en elif)
  • 2.3 Python list (Array, Lijsten)
  • 2.4 Lussen: for, while, break, continue
  • 2.5 Functies: Definities, Parameters en Terugkeerwaarden
  • 2.6 Foutafhandeling: try, except, else, finally

Datatypes

13
  • 3.1 Introductie tot Geavanceerde Datatypes
  • 3.2 Python Tuple
  • 3.3 Python Set
  • 3.4 Python Dictionary
  • 3.5 Werken met Strings en String-methoden
  • 3.6 Collections Module: Krachtige Tools in Python
  • 3.7 Iterators en Generators
  • 3.8 List Comprehensions
  • 3.9 Geavanceerde Sortering
  • 3.10 Werken met Multi-dimensionale Data
  • 3.11 Typing en Datatypes
  • 3.12 Itertools voor Geavanceerde Iteraties
  • 3.13 Data Conversies

Modules

8
  • 4.1 Wat zijn Modules en Waarom zijn ze Belangrijk?
  • 4.2 Werken met Ingebouwde Modules
  • 4.3 Installeren en Gebruiken van Externe Pakketten
  • 4.4 Eigen Modules Maken
  • 4.5 Introductie tot Pakketten
  • 4.6 Importeren en Namespaces Begrijpen
  • 4.7 Geavanceerd: Relatief Importeren
  • 4.8 Organiseren van Grotere Projecten

Data Analyse

3
  • 5.1 Python Dataframe en Data Opschonen met Pandas
  • 5.2 Python Pandas Basisstatistieken en Data-analyse
  • 5.3 Python Numpy (NpArray): De Kracht van Numerieke Berekeningen

Webontwikkeling

5
  • 7.1 Inleiding tot Webontwikkeling
  • 7.2 HTTP-Verzoeken met requests: Communiceren met het Web
  • 7.3 Webscraping met BeautifulSoup: Data van het Web Halen als er geen APIs zijn
  • 7.4 Python Flask, een webserver & API tutorial
  • 7.5 WSGI & WebOb

Deploy

1
  • Deploy met Supervisor op Ubuntu
View Categories
  • Home
  • Documentatie
  • Webontwikkeling
  • 7.4 Python Flask, een webserver & API tutorial

7.4 Python Flask, een webserver & API tutorial

23 minuten leestijd

Stel je voor dat je een eenvoudige website wilt maken of een API wilt bouwen waarmee andere applicaties kunnen communiceren. Het lijkt misschien ingewikkeld, maar met Flask, een populair Python-webframework, kun je dit verrassend snel en eenvoudig realiseren. In dit hoofdstuk leer je hoe je met Flask een webserver opzet, routes definieert, en een solide basis legt voor het bouwen van webapplicaties. Klaar? Laten we beginnen! 🚀

Wat is Flask en waarom gebruiken? #

Flask is een lichtgewicht en flexibel webframework waarmee je alles kunt bouwen, van eenvoudige websites tot complexe webapplicaties. Het staat bekend om zijn eenvoud en uitbreidbaarheid.

Waarom Flask? #

  • Lichtgewicht: Geen onnodige complexiteit. Je voegt alleen toe wat je nodig hebt.
  • Flexibel: Volledig configureerbaar en uitbreidbaar.
  • Gemeenschap: Een grote en actieve gemeenschap met veel documentatie en pakketten.

Een eenvoudige webserver maken #

Een webserver is een programma dat verzoeken van een browser of andere clients ontvangt en daarop reageert, zoals het tonen van een webpagina of het verstrekken van data.

Codevoorbeeld: Een basis Flask-server #

Installeer Flask eerst met:

pip install flask
Python

Code:

from flask import Flask

app = Flask(__name__)  
# Maak een Flask-applicatie

@app.route("/")  
# Definieer een route middels deze annotatie
def home():
    return "Welkom bij mijn Flask-app!"

if __name__ == "__main__":
    app.run(debug=True)  
    # Start de server
Python

Wat gebeurt hier?

  1. Flask(): Dit maakt een nieuwe Flask-applicatie.
  2. @app.route("/"): Dit definieert een route (URL) voor de homepagina (/).
  3. app.run(): Start een lokale webserver op http://127.0.0.1:5000.

Routes en URL’s definiëren #

Met routes koppel je specifieke URL’s aan functies in je applicatie.

Meerdere routes:

@app.route("/about")
def about():
    return "Dit is de over ons-pagina."

@app.route("/user/<username>")
def user_profile(username):
    return f"Welkom, {username}!"
Python

Dynamische URL’s:

  • <username>: Vangt variabele delen van de URL op.
  • Voorbeeld: /user/Joost toont “Welkom, Joost!”.

Statische Content Serveren en Downloads Mogelijk Maken in Flask #

Het serveren van statische bestanden (zoals afbeeldingen, CSS, JavaScript) en het aanbieden van bestanden voor download zijn veelvoorkomende taken bij het bouwen van webapplicaties. Flask biedt ingebouwde ondersteuning om dit eenvoudig te realiseren.

1. Statische Content Serveren #

Statische bestanden zijn bestanden die niet door de server worden gegenereerd, zoals:

  • Afbeeldingen: logo.png
  • CSS-bestanden: style.css
  • JavaScript-bestanden: app.js
De map static #

Flask zoekt standaard naar statische bestanden in een map genaamd static in je project. Je kunt deze bestanden bereiken met de URL /static/<filename>.

Projectstructuur:

my_project/
├── app.py
├── templates/
│   ├── index.html
├── static/
│   ├── css/
│   │   └── style.css
│   ├── js/
│   │   └── app.js
│   └── images/
│       └── logo.png
Python

Code:

from flask import Flask, render_template

app = Flask(__name__)

@app.route("/")
def home():
    return render_template("index.html")  # Gebruik statische bestanden in de template
Python

HTML: templates/index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
    <script src="{{ url_for('static', filename='js/app.js') }}"></script>
</head>
<body>
    <h1>Welkom bij mijn website!</h1>
    <img src="{{ url_for('static', filename='images/logo.png') }}" alt="Logo">
</body>
</html>
Python

Wat gebeurt hier?

  • url_for('static', filename='...'): Genereert de URL naar een bestand in de static-map.
  • Flask serveert de bestanden direct via /static/<filename>.

URL:

  • /static/css/style.css voor de CSS.
  • /static/images/logo.png voor de afbeelding.

2. Downloads Mogelijk Maken #

Soms wil je bestanden beschikbaar stellen voor download, zoals:

  • PDF’s
  • Rapporten
  • Gegevensbestanden (bijv. CSV, JSON)
Gebruik van send_file #

Flask biedt de functie send_file om bestanden te verzenden als onderdeel van een HTTP-response.

Voorbeeld: Een bestand aanbieden voor download

from flask import Flask, send_file

app = Flask(__name__)

@app.route("/download")
def download_file():
    filepath = "files/example.pdf"  
    # Relatief pad naar het bestand
    return send_file(filepath, as_attachment=True)
Python

3. Voorbeeld: In-memory bestand uploaden #

from flask import Flask, request, jsonify
import io

app = Flask(__name__)

# Configuratie voor bestandsgrootte (in bytes) en toegestane types
MAX_FILE_SIZE = 2 * 1024 * 1024  # 2 MB
ALLOWED_CONTENT_TYPES = {"image/jpeg", "image/png", "application/pdf"}

# Middleware om maximale bestandsgrootte af te dwingen
@app.before_request
def check_file_size():
    if request.content_length and request.content_length > MAX_FILE_SIZE:
        return jsonify({"error": "Bestand is te groot. Maximaal 2 MB toegestaan."}), 413  
        # HTTP 413: Payload Too Large

@app.route("/upload", methods=["POST"])
def upload_in_memory():
    uploaded_file = request.files.get("file")
    if not uploaded_file or uploaded_file.filename == "":
        return jsonify({"error": "Geen bestand geüpload"}), 400

    # Controleer bestandstype
    if uploaded_file.content_type not in ALLOWED_CONTENT_TYPES:
        return jsonify({
            "error": f"Bestandstype niet toegestaan. Alleen de volgende types zijn toegestaan: {', '.join(ALLOWED_CONTENT_TYPES)}"
        }), 415  # HTTP 415: Unsupported Media Type

    # Lees de inhoud van het bestand in memory
    file_content = uploaded_file.read()  # Bytes
    file_name = uploaded_file.filename
    content_type = uploaded_file.content_type

    # Voorbeeld: Verwerk de inhoud (hier printen, maar kan ook naar een database)
    print(f"Bestand ontvangen: {file_name}")
    print(f"Inhoudstype: {content_type}")
    print(f"Voorbeeldinhoud: {file_content[:50]}...")  
    # Toon alleen de eerste 50 bytes

    # Opslaan in een database (pseudocode, afhankelijk van database):
    # save_to_database(filename=file_name, content=file_content, content_type=content_type)

    return jsonify({
        "message": "Bestand succesvol verwerkt in-memory",
        "filename": file_name,
        "content_type": content_type
    })

# HTML voor uploaden
@app.route("/", methods=["GET"])
def upload_form():
    return '''
    <form method="post" enctype="multipart/form-data" action="/upload">
        <input type="file" name="file">
        <input type="submit">
    </form>
    '''

if __name__ == "__main__":
    app.run(debug=True)
Python

Wat gebeurt hier? #
  1. In-memory verwerking:
    • uploaded_file.read(): Leest de inhoud van het bestand als bytes. Het bestand wordt volledig in het geheugen geladen.
  2. Gegevens van het bestand:
    • uploaded_file.filename: De originele naam van het bestand.
    • uploaded_file.content_type: Het MIME-type van het bestand, zoals text/plain of image/png.
  3. Opslaan in een database:
    • In plaats van het bestand op te slaan als een fysiek bestand, kun je de inhoud (file_content) opslaan in een database zoals PostgreSQL of MongoDB. Dit is afhankelijk van je database-configuratie.

REST Endpoint Uitleg: GET, POST, PUT, DELETE #

REST (Representational State Transfer) is een architectuurstijl waarmee je API’s bouwt die de presentatie (frontend) en logica/data (backend) scheiden. Dit maakt het gemakkelijker om schaalbare en flexibele applicaties te ontwikkelen. Een belangrijk aspect van REST is het gebruik van HTTP-methoden zoals GET, POST, PUT, en DELETE om verschillende acties uit te voeren op data.

Hier breiden we ons REST-endpoint uit om alle vier de HTTP-methoden te ondersteunen.

GET: Gegevens Opvragen #

Een GET-verzoek wordt gebruikt om gegevens op te halen. In dit voorbeeld vragen we een lijst met gebruikers op.

Voorbeeld: #
from flask import Flask, jsonify

app = Flask(__name__)

# Mock database
users = [{"id": 1, "name": "Alice"}, {"id": 2, "name": "Bob"}]

@app.route("/api/users", methods=["GET"])
def get_users():
    return jsonify(users)
Python

Wat gebeurt hier?

  • jsonify(users): Zet de users-lijst om naar JSON en retourneert deze.
  • methods=["GET"]: Beperkt dit endpoint tot alleen GET-verzoeken.

Uitvoer: Wanneer je GET /api/users uitvoert, ontvang je een lijst met gebruikers in JSON-formaat:

[
  {"id": 1, "name": "Alice"},
  {"id": 2, "name": "Bob"}
]
Python

POST: Nieuwe Data Toevoegen #

Met POST kun je nieuwe gegevens naar de server sturen om toe te voegen aan een database.

Voorbeeld: #
from flask import request

@app.route("/api/users", methods=["POST"])
def create_user():
    new_user = request.json  
    # Ontvang de JSON-data uit de aanvraag
    users.append(new_user)  
    # Voeg de nieuwe gebruiker toe aan de lijst
    return jsonify(new_user), 201  
    # Retourneer de nieuwe gebruiker met status 201 (Created)
Python

Wat gebeurt hier?

  • request.json: Haalt de JSON-data op die is verstuurd in het POST-verzoek.
  • users.append(new_user): Voegt de nieuwe gebruiker toe aan de lijst.
  • Statuscode 201: Geeft aan dat een nieuwe resource succesvol is aangemaakt.

Uitvoer: Stuur een POST-verzoek met JSON-data:

{
  "id": 3,
  "name": "Charlie"
}
Python

PUT: Gegevens Bewerken #

Met PUT kun je bestaande gegevens in de database bijwerken.

Voorbeeld: #
@app.route("/api/users/<int:user_id>", methods=["PUT"])
def update_user(user_id):
    updated_user = request.json
    for user in users:
        if user["id"] == user_id:
            user.update(updated_user)  
            # Werk de gebruiker bij
            return jsonify(user)
    return jsonify({"error": "User not found"}), 404
Python

Wat gebeurt hier?

  • <int:user_id>: Maakt het mogelijk een specifieke gebruiker te selecteren via de URL.
  • user.update(updated_user): Werk de gegevens van de gebruiker bij met de nieuwe data.
  • Statuscode 404: Retourneert een foutmelding als de gebruiker niet wordt gevonden.

Uitvoer: Stuur een PUT-verzoek naar /api/users/1 met JSON-data:

{
  "name": "Alice Updated"
}
Python

Reactie van de server:

{
  "id": 1,
  "name": "Alice Updated"
}
Python

DELETE: Gegevens Verwijderen #

Met DELETE kun je gegevens uit de database verwijderen.

Voorbeeld: #
@app.route("/api/users/<int:user_id>", methods=["DELETE"])
def delete_user(user_id):
    for user in users:
        if user["id"] == user_id:
            users.remove(user)  # Verwijder de gebruiker
            return jsonify({"message": "User deleted"})
    return jsonify({"error": "User not found"}), 404
Python

Wat gebeurt hier?

  • users.remove(user): Verwijdert de gebruiker uit de lijst.
  • Statuscode 404: Geeft een foutmelding als de gebruiker niet wordt gevonden.

Uitvoer: Stuur een DELETE-verzoek naar /api/users/2.

Reactie van de server:

{
  "message": "User deleted"
}
Python

Samengevoegd Voorbeeld #

Hier is een samenvatting van alle vier de HTTP-methoden in één API:

from flask import Flask, jsonify, request

app = Flask(__name__)

# Mock database
users = [{"id": 1, "name": "Alice"}, {"id": 2, "name": "Bob"}]

@app.route("/api/users", methods=["GET"])
def get_users():
    return jsonify(users)

@app.route("/api/users", methods=["POST"])
def create_user():
    new_user = request.json
    users.append(new_user)
    return jsonify(new_user), 201

@app.route("/api/users/<int:user_id>", methods=["PUT"])
def update_user(user_id):
    updated_user = request.json
    for user in users:
        if user["id"] == user_id:
            user.update(updated_user)
            return jsonify(user)
    return jsonify({"error": "User not found"}), 404

@app.route("/api/users/<int:user_id>", methods=["DELETE"])
def delete_user(user_id):
    for user in users:
        if user["id"] == user_id:
            users.remove(user)
            return jsonify({"message": "User deleted"})
    return jsonify({"error": "User not found"}), 404

if __name__ == "__main__":
    app.run(debug=True)
Python

Samenvatting van de Methodes #

MethodeDoelVoorbeeldBeschrijving
GETGegevens ophalen/api/usersRetourneert een lijst met gebruikers.
POSTNieuwe gegevens toevoegen/api/usersVoegt een nieuwe gebruiker toe.
PUTBestaande gegevens bijwerken/api/users/<user_id>Werkt de gegevens van een gebruiker bij.
DELETEGegevens verwijderen/api/users/<user_id>Verwijdert een gebruiker.

Belangrijke Tips voor REST API’s #

  1. JSON-data gebruiken: Zorg ervoor dat je consistent JSON gebruikt voor communicatie tussen client en server.
  2. Statuscodes retourneren: Geef altijd een passende statuscode terug, zoals:
    • 200 OK: Succesvol uitgevoerd.
    • 201 Created: Nieuwe resource aangemaakt.
    • 404 Not Found: Resource niet gevonden.
  3. Valideer data: Controleer of de gegevens die je ontvangt correct en compleet zijn.
  4. Beveiliging: Voeg authenticatie toe aan je API om ongeautoriseerde toegang te voorkomen.

Soorten Parameters in Flask #

In Flask kun je verschillende soorten parameters gebruiken in je routes om gegevens van de client te ontvangen. Parameters helpen je om dynamische URL’s te maken waarmee je specifieke informatie kunt verwerken, zoals een gebruiker-ID of een categorie.

Hier zijn de belangrijkste soorten parameters in Flask:

1. Dynamische Route Parameters #

Deze parameters worden gedefinieerd in de route en zijn zichtbaar in de URL.

Standaard Parameter #

Flask behandelt standaard parameters als strings.

Voorbeeld:

@app.route("/user/<username>")
def show_user(username):
    return f"Hallo, {username}!"
Python

Gedefinieerd Type Parameter #

Je kunt een type specificeren voor de parameter. Dit voorkomt dat verkeerde typen worden doorgegeven.

Voorbeeld met type int:

@app.route("/user/<int:user_id>")
def show_user_by_id(user_id):
    return f"Gebruiker-ID: {user_id}"
Python

URL: /user/123
Output: Gebruiker-ID: 123

Als je /user/abc probeert, retourneert Flask automatisch een 404-fout omdat abc geen integer is.

Beschikbare typen:

  • string (standaard): Accepteert elk teken.
  • int: Accepteert alleen gehele getallen.
  • float: Accepteert getallen met decimalen.
  • path: Accepteert strings inclusief slashes (/).
  • uuid: Accepteert een UUID-formaat.

2. Query Parameters #

Query parameters worden toegevoegd aan de URL na een vraagteken (?) en worden meestal gebruikt voor optionele of aanvullende gegevens.

Voorbeeld:

@app.route("/search")
def search():
    term = request.args.get("q", default="geen zoekterm")
    return f"Zoekresultaten voor: {term}"
Python

URL: /search?q=python
Output: Zoekresultaten voor: python

URL zonder parameter: /search
Output: Zoekresultaten voor: geen zoekterm

3. Formulier Parameters #

Bij een POST-verzoek kun je gegevens verzenden via een HTML-formulier en deze ophalen met request.form.

Voorbeeld:

@app.route("/submit", methods=["POST"])
def submit_form():
    naam = request.form.get("naam")
    return f"Formulier ontvangen van: {naam}"
Python

HTML:

<form method="post" action="/submit">
  <input type="text" name="naam" placeholder="Naam">
  <button type="submit">Verzenden</button>
</form>
Python

4. Headers #

Je kunt extra gegevens via headers verzenden, bijvoorbeeld voor authenticatie.

Voorbeeld:

@app.route("/auth")
def auth():
    token = request.headers.get("Authorization")
    return f"Token ontvangen: {token}"
Python

Gebruik: Voeg een header toe aan het verzoek:

Authorization: Bearer mijn_token
Python

Werken met Cookies in Flask #

Cookies zijn kleine stukjes data die worden opgeslagen in de browser van de gebruiker. Ze worden vaak gebruikt om informatie te bewaren, zoals inlogstatus, gebruikersvoorkeuren, of sessiegegevens. In Flask kun je cookies gemakkelijk instellen, ophalen, en verwijderen.

1. Hoe werken cookies? #

Cookies worden verzonden tussen de client (browser) en de server bij elk verzoek. Ze bestaan uit:

  • Naam: De sleutel van de cookie.
  • Waarde: De gegevens die worden opgeslagen.
  • Vervaldatum: Optioneel, bepaalt hoe lang de cookie geldig blijft.
  • Domein en pad: Optioneel, bepalen waar de cookie beschikbaar is.
  • Beveiliging: Optioneel, zoals alleen HTTPS of HttpOnly (niet toegankelijk voor JavaScript).

2. Cookies instellen in Flask #

In Flask kun je een cookie instellen met de set_cookie()-methode op een Response-object.

Voorbeeld: Cookie instellen #
from flask import Flask, request, make_response

app = Flask(__name__)

@app.route("/set-cookie")
def set_cookie():
    resp = make_response("Cookie is ingesteld!")
    resp.set_cookie("username", "Joost")  
    # Stel een cookie in met naam en waarde
    return resp
Python

Wat gebeurt hier?

  • make_response(): Hiermee maak je een aanpasbaar Response-object.
  • set_cookie("username", "Joost"): Stelt een cookie in met de naam username en waarde Joost.

3. Cookies ophalen #

Cookies die door de browser zijn opgeslagen, kun je ophalen met de request.cookies-dictionary.

Voorbeeld: Cookie ophalen #
@app.route("/get-cookie")
def get_cookie():
    username = request.cookies.get("username")  
    # Haal de waarde van de cookie op
    if username:
        return f"Hallo, {username}!"
    return "Geen cookie gevonden."
Python

Wat gebeurt hier?

  • request.cookies.get("username"): Haalt de waarde van de cookie username op. Retourneert None als de cookie niet bestaat.

4. Cookies verwijderen #

Je kunt een cookie verwijderen door deze in te stellen met een verlopen datum.

Voorbeeld: Cookie verwijderen #
@app.route("/delete-cookie")
def delete_cookie():
    resp = make_response("Cookie is verwijderd!")
    resp.set_cookie("username", "", expires=0)  
    # Stel de cookie in met een verlopen tijd
    return resp
Python

Wat gebeurt hier?

  • expires=0: Zet de vervaldatum op 0, waardoor de browser de cookie onmiddellijk verwijdert.

5. Cookies met extra beveiliging #

Bij gevoelige data moet je extra beveiligingsopties instellen voor cookies.

Belangrijke opties: #
  1. secure=True: Zorgt ervoor dat cookies alleen via HTTPS worden verzonden.
  2. httponly=True: Voorkomt dat cookies toegankelijk zijn via JavaScript, wat XSS-aanvallen helpt voorkomen.
  3. samesite="Strict": Beperkt cookies tot hetzelfde domein, wat CSRF-aanvallen helpt voorkomen.
Voorbeeld: Beveiligde cookie instellen #
@app.route("/secure-cookie")
def secure_cookie():
    resp = make_response("Veilige cookie ingesteld!")
    resp.set_cookie(
        "secure_data", 
        "gevoelige_informatie", 
        secure=True,  
        # Alleen via HTTPS
        httponly=True,  
        # Niet toegankelijk via JavaScript
        samesite="Strict"  
        # Alleen toegankelijk binnen hetzelfde domein
    )
    return resp
Python

Authenticatie en Autorisatie in Flask #

Bij het bouwen van webapplicaties en API’s is authenticatie (wie ben je?) en autorisatie (wat mag je doen?) cruciaal om toegang tot gevoelige gegevens en functionaliteiten te beheren. Flask biedt verschillende methoden om authenticatie en autorisatie te implementeren, van eenvoudige oplossingen tot meer geavanceerde systemen.

Hier is een overzicht van de meest gebruikte opties in Flask:

1. Simpele Authenticatie met HTTP Basic Auth #

Bij HTTP Basic Auth stuurt de client een gebruikersnaam en wachtwoord mee in de HTTP-header.

Voorbeeld: Basis Authenticatie #

Met de extensie Flask-HTTPAuth kun je eenvoudig Basic Auth implementeren.

Installatie:

pip install flask-httpauth
Python

Code:

from flask import Flask, jsonify
from flask_httpauth import HTTPBasicAuth

app = Flask(__name__)
auth = HTTPBasicAuth()

# Dummy gebruikersgegevens
USERS = {
    "admin": "secret",
    "user": "password"
}

@auth.verify_password
def verify_password(username, password):
    return USERS.get(username) == password

@app.route("/secure-data")
@auth.login_required
def secure_data():
    return jsonify({"message": f"Welkom, {auth.username()}!"})
Python

Wat gebeurt hier?

  • @auth.verify_password: Verifieert gebruikersnaam en wachtwoord.
  • @auth.login_required: Beschermt routes; alleen geauthenticeerde gebruikers hebben toegang.

2. Token-based Authenticatie #

Bij Token-based authenticatie krijgt de client een token na succesvolle login. Dit token wordt gebruikt voor toekomstige verzoeken, zonder dat inloggegevens telkens opnieuw worden verzonden.

Voorbeeld: Simpele Token Authenticatie #
from flask import Flask, request, jsonify

app = Flask(__name__)

# Dummy gebruikers en tokens
TOKENS = {"example_token": "admin"}

@app.route("/login", methods=["POST"])
def login():
    username = request.json.get("username")
    password = request.json.get("password")
    if username == "admin" and password == "secret":
        return jsonify({"token": "example_token"})
    return jsonify({"error": "Onjuiste inloggegevens"}), 401

@app.route("/protected")
def protected():
    token = request.headers.get("Authorization")
    if token in TOKENS:
        return jsonify({"message": f"Welkom, {TOKENS[token]}!"})
    return jsonify({"error": "Ongeldig token"}), 403
Python

Wat gebeurt hier?

  • Bij login ontvang je een token.
  • Het token wordt meegestuurd in de Authorization-header voor beveiligde routes.

3. JSON Web Tokens (JWT) #

JWT is een populaire manier om stateless authenticatie te implementeren. Een JWT is een gecodeerde string die informatie over de gebruiker bevat en door de server kan worden gevalideerd zonder een sessie op te slaan.

Installatie: #
pip install flask-jwt-extended
Python

Code:

from flask import Flask, request, jsonify
from flask_jwt_extended import JWTManager, create_access_token, jwt_required, get_jwt_identity

app = Flask(__name__)
app.config["JWT_SECRET_KEY"] = "mijngeheimestsleutel"
jwt = JWTManager(app)

# Dummy gebruikers
USERS = {"admin": "secret"}

@app.route("/login", methods=["POST"])
def login():
    username = request.json.get("username")
    password = request.json.get("password")
    if USERS.get(username) == password:
        token = create_access_token(identity=username)
        return jsonify({"token": token})
    return jsonify({"error": "Onjuiste inloggegevens"}), 401

@app.route("/dashboard")
@jwt_required()
def dashboard():
    current_user = get_jwt_identity()
    return jsonify({"message": f"Welkom, {current_user}!"})
Python

Wat gebeurt hier?

  1. Login: Na succesvolle login wordt een JWT-token gegenereerd.
  2. Toegang: Routes met @jwt_required() vereisen een geldig JWT-token.

4. OAuth 2.0 en OpenID Connect #

Voor integraties met externe providers (bijv. Google, Facebook) kun je OAuth 2.0 gebruiken. Met extensies zoals Flask-OAuthlib of Authlib kun je OAuth eenvoudig implementeren.

Installatie: #
pip install authlib
Python

Code:

from flask import Flask, redirect, url_for
from authlib.integrations.flask_client import OAuth

app = Flask(__name__)
app.secret_key = "mijngeheimestsleutel"

oauth = OAuth(app)
google = oauth.register(
    name="google",
    client_id="GOOGLE_CLIENT_ID",
    client_secret="GOOGLE_CLIENT_SECRET",
    access_token_url="https://accounts.google.com/o/oauth2/token",
    authorize_url="https://accounts.google.com/o/oauth2/auth",
    api_base_url="https://www.googleapis.com/oauth2/v1/",
    client_kwargs={"scope": "openid email profile"},
)

@app.route("/")
def home():
    return "Welkom! <a href='/login'>Log in met Google</a>"

@app.route("/login")
def login():
    return google.authorize_redirect(url_for("authorize", _external=True))

@app.route("/authorize")
def authorize():
    token = google.authorize_access_token()
    user_info = google.get("userinfo").json()
    return f"Welkom, {user_info['email']}!"
Python

Wat gebeurt hier?

  1. Login: De gebruiker logt in bij Google.
  2. Token: De applicatie ontvangt een token van Google.
  3. Profielgegevens: Toegang tot gegevens zoals e-mailadres en naam via de Google API.

5. Rollen en Autorisatie #

Autorisatie bepaalt welke acties een gebruiker mag uitvoeren. Dit kan worden beheerd op basis van rollen.

Voorbeeld: Rollen met Decorators #
from functools import wraps

USERS = {"admin": {"password": "secret", "role": "admin"},
         "user": {"password": "password", "role": "user"}}

def role_required(role):
    def decorator(f):
        @wraps(f)
        def decorated_function(*args, **kwargs):
            username = request.json.get("username")
            user = USERS.get(username)
            if user and user["role"] == role:
                return f(*args, **kwargs)
            return jsonify({"error": "Toegang geweigerd"}), 403
        return decorated_function
    return decorator

@app.route("/admin", methods=["POST"])
@role_required("admin")
def admin_panel():
    return "Welkom in het admin-paneel!"
Python

Wat gebeurt hier?

  • role_required(): Controleert of de gebruiker de juiste rol heeft.
  • Alleen gebruikers met de rol admin mogen toegang tot het admin-paneel.

REST API Structuur en Versiebeheer in Flask #

Wanneer je een grotere REST API bouwt, is het belangrijk om een goede bestandsstructuur te gebruiken. Dit zorgt voor overzicht, onderhoudbaarheid en schaalbaarheid, vooral als je met een team werkt of je project in de toekomst wilt uitbreiden.

Hier is een gids voor het structureren van een REST API in Flask, inclusief een aanpak voor versiebeheer.

1. Basisprincipes van Structuur #

Een goed gestructureerd project maakt gebruik van:

  1. Modulariteit: Splits routes, modellen en configuratie op in afzonderlijke bestanden.
  2. Blueprints: Een ingebouwde functionaliteit in Flask om routes logisch te organiseren.
  3. Versiebeheer: Maak verschillende versies van je API (bijvoorbeeld v1, v2) om wijzigingen beheersbaar te maken.
  4. Configuratiebeheer: Houd omgevingsspecifieke instellingen apart (bijvoorbeeld voor ontwikkel- en productieomgevingen).

2. Bestandsstructuur #

Hier is een voorbeeld van een eenvoudige projectstructuur:

my_api/
├── app/
│   ├── __init__.py         # Initialisatie van de Flask-app
│   ├── config.py           # Configuratiebeheer
│   ├── models/             # Modellen (bijv. database)
│   │   └── __init__.py
│   ├── routes/             # Routes per module
│   │   ├── __init__.py
│   │   ├── users.py        # Routes voor gebruikers
│   │   └── products.py     # Routes voor producten
│   └── utils/              # Helperfuncties
│       └── validators.py   # Validatiefuncties
├── migrations/             # Database migraties (bij gebruik van SQLAlchemy)
├── requirements.txt        # Vereiste pakketten
├── run.py                  # Het startpunt van de applicatie
└── tests/                  # Unit tests
    └── test_users.py
Python

3. Flask App Initialiseren #

De initialisatie gebeurt in app/__init__.py. Hier configureer je de Flask-app, registreer je blueprints en laad je instellingen.

Code: app/__init__.py

from flask import Flask
from app.routes.users import users_blueprint
from app.routes.products import products_blueprint

def create_app(config_class="app.config.Config"):
    app = Flask(__name__)
    app.config.from_object(config_class)

    # Registreer blueprints
    app.register_blueprint(users_blueprint, url_prefix="/api/v1/users")
    app.register_blueprint(products_blueprint, url_prefix="/api/v1/products")

    return app
Python

4. Configuratiebeheer #

Gebruik een aparte config.py voor instellingen zoals debugmodus, database-URL’s, of API-sleutels.

Code: app/config.py

import os

class Config:
    SECRET_KEY = os.environ.get("SECRET_KEY", "mijn_standaard_sleutel")
    DEBUG = False
    DATABASE_URI = os.environ.get("DATABASE_URI", "sqlite:///app.db")

class DevelopmentConfig(Config):
    DEBUG = True

class ProductionConfig(Config):
    DEBUG = False
Python

Je kunt de configuratie laden door het omgevingsvariabele FLASK_ENV te gebruiken.

5. Routes Organiseren met Blueprints #

Blueprints maken het gemakkelijk om routes logisch te groeperen.

Code: app/routes/users.py

from flask import Blueprint, jsonify, request

users_blueprint = Blueprint("users", __name__)

# Mock database
users = [{"id": 1, "name": "Alice"}, {"id": 2, "name": "Bob"}]

@users_blueprint.route("/", methods=["GET"])
def get_users():
    return jsonify(users)

@users_blueprint.route("/", methods=["POST"])
def create_user():
    new_user = request.json
    users.append(new_user)
    return jsonify(new_user), 201
Python

Code: app/routes/products.py

from flask import Blueprint, jsonify

products_blueprint = Blueprint("products", __name__)

@products_blueprint.route("/", methods=["GET"])
def get_products():
    return jsonify([{"id": 1, "name": "Laptop"}])
Python

6. Versiebeheer #

Je kunt eenvoudig meerdere versies van je API beheren door verschillende versies in te richten als aparte blueprints of modules.

Structuur:

my_api/
└── app/
    ├── routes/
    │   ├── v1/
    │   │   ├── __init__.py
    │   │   ├── users.py
    │   │   └── products.py
    │   └── v2/
    │       ├── __init__.py
    │       ├── users.py
    │       └── products.py
Python

Code: app/routes/v1/__init__.py

from flask import Blueprint

v1_blueprint = Blueprint("v1", __name__)

from .users import users_blueprint
from .products import products_blueprint

# Registreer sub-blueprints
v1_blueprint.register_blueprint(users_blueprint, url_prefix="/users")
v1_blueprint.register_blueprint(products_blueprint, url_prefix="/products")
Python

Code: app/__init__.py

from flask import Flask
from app.routes.v1 import v1_blueprint
from app.routes.v2 import v2_blueprint

def create_app(config_class="app.config.Config"):
    app = Flask(__name__)
    app.config.from_object(config_class)

    # Versiebeheer: registreer v1 en v2
    app.register_blueprint(v1_blueprint, url_prefix="/api/v1")
    app.register_blueprint(v2_blueprint, url_prefix="/api/v2")

    return app
Python

7. Run.py: Het Startpunt #

Code: run.py

from app import create_app

app = create_app()

if __name__ == "__main__":
    app.run()
Python

Voordelen van deze Structuur #

  1. Overzichtelijk: Logische scheiding van verantwoordelijkheden.
  2. Herbruikbaarheid: Routes en functionaliteit zijn eenvoudig te verplaatsen of uit te breiden.
  3. Versiebeheer: Nieuwe API-versies kunnen parallel bestaan zonder bestaande functionaliteit te breken.

Samenvatting #

Met Flask kun je snel en eenvoudig krachtige webapplicaties bouwen. Van het definiëren van routes tot het verwerken van formulieren en het bouwen van RESTful API’s, Flask biedt alles wat je nodig hebt om te starten met webontwikkeling. Combineer deze kennis en bouw je eigen projecten, stap voor stap! 🚀🎉

Updated on februari 7, 2025
7.3 Webscraping met BeautifulSoup: Data van het Web Halen als er geen APIs zijn7.5 WSGI & WebOb
Inhoudsopgave
  • Wat is Flask en waarom gebruiken?
    • Waarom Flask?
  • Een eenvoudige webserver maken
    • Codevoorbeeld: Een basis Flask-server
  • Routes en URL's definiëren
  • Statische Content Serveren en Downloads Mogelijk Maken in Flask
    • 1. Statische Content Serveren
      • De map static
    • 2. Downloads Mogelijk Maken
      • Gebruik van send_file
    • 3. Voorbeeld: In-memory bestand uploaden
      • Wat gebeurt hier?
  • REST Endpoint Uitleg: GET, POST, PUT, DELETE
    • GET: Gegevens Opvragen
      • Voorbeeld:
    • POST: Nieuwe Data Toevoegen
      • Voorbeeld:
    • PUT: Gegevens Bewerken
      • Voorbeeld:
    • DELETE: Gegevens Verwijderen
      • Voorbeeld:
  • Samengevoegd Voorbeeld
    • Samenvatting van de Methodes
    • Belangrijke Tips voor REST API's
  • Soorten Parameters in Flask
    • 1. Dynamische Route Parameters
      • Standaard Parameter
      • Gedefinieerd Type Parameter
    • 2. Query Parameters
    • 3. Formulier Parameters
    • 4. Headers
  • Werken met Cookies in Flask
    • 1. Hoe werken cookies?
    • 2. Cookies instellen in Flask
      • Voorbeeld: Cookie instellen
    • 3. Cookies ophalen
      • Voorbeeld: Cookie ophalen
    • 4. Cookies verwijderen
      • Voorbeeld: Cookie verwijderen
    • 5. Cookies met extra beveiliging
      • Belangrijke opties:
      • Voorbeeld: Beveiligde cookie instellen
  • Authenticatie en Autorisatie in Flask
  • 1. Simpele Authenticatie met HTTP Basic Auth
    • Voorbeeld: Basis Authenticatie
    • 2. Token-based Authenticatie
      • Voorbeeld: Simpele Token Authenticatie
    • 3. JSON Web Tokens (JWT)
      • Installatie:
    • 4. OAuth 2.0 en OpenID Connect
      • Installatie:
    • 5. Rollen en Autorisatie
      • Voorbeeld: Rollen met Decorators
  • REST API Structuur en Versiebeheer in Flask
    • 1. Basisprincipes van Structuur
    • 2. Bestandsstructuur
    • 3. Flask App Initialiseren
    • 4. Configuratiebeheer
    • 5. Routes Organiseren met Blueprints
  • 6. Versiebeheer
    • 7. Run.py: Het Startpunt
    • Voordelen van deze Structuur
  • Samenvatting
Programmeren in Python

Leer python op je eigen tempo met mooie interactieve hedendaagse voorbeelden.

© Copyright 2025 Programmeren in Python.
Sign inSign up

Sign in

Don’t have an account? Sign up
Lost your password?

Sign up

Already have an account? Sign in