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
PythonCode:
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
PythonWat gebeurt hier?
Flask()
: Dit maakt een nieuwe Flask-applicatie.@app.route("/")
: Dit definieert een route (URL) voor de homepagina (/
).app.run()
: Start een lokale webserver ophttp://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}!"
PythonDynamische 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
PythonCode:
from flask import Flask, render_template
app = Flask(__name__)
@app.route("/")
def home():
return render_template("index.html") # Gebruik statische bestanden in de template
PythonHTML: 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>
PythonWat gebeurt hier?
url_for('static', filename='...')
: Genereert de URL naar een bestand in destatic
-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)
Python3. 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)
PythonWat gebeurt hier? #
- In-memory verwerking:
uploaded_file.read()
: Leest de inhoud van het bestand als bytes. Het bestand wordt volledig in het geheugen geladen.
- Gegevens van het bestand:
uploaded_file.filename
: De originele naam van het bestand.uploaded_file.content_type
: Het MIME-type van het bestand, zoalstext/plain
ofimage/png
.
- 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.
- In plaats van het bestand op te slaan als een fysiek bestand, kun je de inhoud (
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)
PythonWat gebeurt hier?
jsonify(users)
: Zet deusers
-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"}
]
PythonPOST: 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)
PythonWat 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"
}
PythonPUT: 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
PythonWat 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"
}
PythonReactie van de server:
{
"id": 1,
"name": "Alice Updated"
}
PythonDELETE: 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
PythonWat 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"
}
PythonSamengevoegd 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)
PythonSamenvatting van de Methodes #
Methode | Doel | Voorbeeld | Beschrijving |
---|---|---|---|
GET | Gegevens ophalen | /api/users | Retourneert een lijst met gebruikers. |
POST | Nieuwe gegevens toevoegen | /api/users | Voegt een nieuwe gebruiker toe. |
PUT | Bestaande gegevens bijwerken | /api/users/<user_id> | Werkt de gegevens van een gebruiker bij. |
DELETE | Gegevens verwijderen | /api/users/<user_id> | Verwijdert een gebruiker. |
Belangrijke Tips voor REST API’s #
- JSON-data gebruiken: Zorg ervoor dat je consistent JSON gebruikt voor communicatie tussen client en server.
- Statuscodes retourneren: Geef altijd een passende statuscode terug, zoals:
200 OK
: Succesvol uitgevoerd.201 Created
: Nieuwe resource aangemaakt.404 Not Found
: Resource niet gevonden.
- Valideer data: Controleer of de gegevens die je ontvangt correct en compleet zijn.
- 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}!"
PythonGedefinieerd 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}"
PythonURL: /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}"
PythonURL: /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}"
PythonHTML:
<form method="post" action="/submit">
<input type="text" name="naam" placeholder="Naam">
<button type="submit">Verzenden</button>
</form>
Python4. 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}"
PythonGebruik: Voeg een header toe aan het verzoek:
Authorization: Bearer mijn_token
PythonWerken 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
PythonWat gebeurt hier?
make_response()
: Hiermee maak je een aanpasbaarResponse
-object.set_cookie("username", "Joost")
: Stelt een cookie in met de naamusername
en waardeJoost
.
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."
PythonWat gebeurt hier?
request.cookies.get("username")
: Haalt de waarde van de cookieusername
op. RetourneertNone
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
PythonWat 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: #
secure=True
: Zorgt ervoor dat cookies alleen via HTTPS worden verzonden.httponly=True
: Voorkomt dat cookies toegankelijk zijn via JavaScript, wat XSS-aanvallen helpt voorkomen.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
PythonAuthenticatie 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
PythonCode:
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()}!"})
PythonWat 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
PythonWat 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
PythonCode:
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}!"})
PythonWat gebeurt hier?
- Login: Na succesvolle login wordt een JWT-token gegenereerd.
- 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
PythonCode:
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']}!"
PythonWat gebeurt hier?
- Login: De gebruiker logt in bij Google.
- Token: De applicatie ontvangt een token van Google.
- 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!"
PythonWat 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:
- Modulariteit: Splits routes, modellen en configuratie op in afzonderlijke bestanden.
- Blueprints: Een ingebouwde functionaliteit in Flask om routes logisch te organiseren.
- Versiebeheer: Maak verschillende versies van je API (bijvoorbeeld
v1
,v2
) om wijzigingen beheersbaar te maken. - 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
Python3. 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
Python4. 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
PythonJe 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
PythonCode: 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"}])
Python6. 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
PythonCode: 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")
PythonCode: 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
Python7. Run.py: Het Startpunt #
Code: run.py
from app import create_app
app = create_app()
if __name__ == "__main__":
app.run()
PythonVoordelen van deze Structuur #
- Overzichtelijk: Logische scheiding van verantwoordelijkheden.
- Herbruikbaarheid: Routes en functionaliteit zijn eenvoudig te verplaatsen of uit te breiden.
- 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! 🚀🎉