CS50 Woche 9: Flask

Ein umfassendes Cheatsheet

Tipp: Um dieses Dokument als PDF zu speichern, klicken Sie auf "Preview", öffnen Sie dann das Druckmenü Ihres Browsers (Strg+P oder Cmd+P) und wählen Sie "Als PDF speichern".

1. Flask Grundlagen

Flask ist ein minimalistisches Web-Framework für Python. Es ist ideal, um schnell robuste und erweiterbare Webanwendungen zu erstellen.

Grundlegende App-Struktur

Jede Flask-Anwendung benötigt eine Instanz der Flask-Klasse und mindestens eine "Route", um Anfragen zu bearbeiten.

from flask import Flask, render_template, request

# App konfigurieren
app = Flask(__name__)

# Eine "Route" definieren, die auf die URL "/" reagiert
@app.route("/")
def index():
    # Rendert die HTML-Datei aus dem 'templates'-Ordner
    return render_template("index.html")

Wichtige Ordnerstruktur

Flask erwartet eine bestimmte Organisation Ihrer Dateien:

/meine_app
|-- app.py              # Ihre Haupt-Python-Datei
|-- /templates
|   |-- index.html      # HTML-Dateien
|   |-- layout.html
|-- /static
|   |-- styles.css      # CSS, JS, Bilder

2. Templates mit Jinja

Mit der Jinja2-Templating-Engine können Sie Python-ähnliche Logik direkt in Ihr HTML einbetten, um dynamische Seiten zu erstellen.

Spezielle Jinja-Syntax

Beispiel: Schleife und Bedingung

<ul>
    {% for item in einkaufsliste %}
        <li>{{ item }}</li>
    {% endfor %}
</ul>

{% if user %}
    <p>Willkommen, {{ user.name }}!</p>
{% else %}
    <p>Bitte einloggen.</p>
{% endif %}

Template-Vererbung (Layouts)

Vermeiden Sie Code-Wiederholung, indem Sie ein Basis-Layout definieren und Blöcke in anderen Templates überschreiben.

<!-- templates/layout.html -->
<!DOCTYPE html>
<html>
<head><title>Meine App</title></head>
<body>
    {% block body %}{% endblock %}
</body>
</html>

<!-- templates/index.html -->
{% extends "layout.html" %}

{% block body %}
    <h1>Das ist die Startseite!</h1>
{% endblock %}

3. Formulare und Anfragen

Benutzereingaben werden typischerweise über HTML-Formulare gesammelt und mit GET- oder POST-Anfragen an den Server gesendet.

GET vs. POST

Daten verarbeiten

Importieren Sie das request-Objekt, um auf Formulardaten zuzugreifen. Die Route muss die erlaubten Methoden definieren.

from flask import request, redirect

@app.route("/login", methods=["GET", "POST"])
def login():
    if request.method == "POST":
        # Daten aus dem Formular holen (bei POST)
        username = request.form.get("username")
        # Weiterleiten nach Verarbeitung
        return redirect("/") 
    else:
        # Formular bei GET-Anfrage anzeigen
        return render_template("login.html")

Verwenden Sie request.form.get("name") für POST-Daten und request.args.get("name") für URL-Parameter (GET).

4. Sessions

Sessions ermöglichen es, Informationen über mehrere Anfragen eines Benutzers hinweg zu speichern (z.B. wer eingeloggt ist). Sie basieren auf Cookies.

Session konfigurieren und verwenden

from flask import session
from flask_session import Session

# App konfigurieren, um dateisystembasierte Sessions zu nutzen
app.config["SESSION_PERMANENT"] = False
app.config["SESSION_TYPE"] = "filesystem"
Session(app)

@app.route("/login", methods=["POST"])
def login():
    # Nach erfolgreicher Anmeldung...
    username = request.form.get("username")
    session["user_id"] = username  # Wert in der Session speichern
    return redirect("/")

@app.route("/logout")
def logout():
    session.clear()  # Alle Daten aus der Session löschen
    return redirect("/")

In anderen Routen können Sie dann mit if "user_id" in session: überprüfen, ob ein Benutzer angemeldet ist.

5. Datenbanken mit CS50 SQL

Die CS50-Bibliothek vereinfacht die Interaktion mit SQL-Datenbanken erheblich und schützt automatisch vor SQL-Injection.

Beispiel: Abfragen und Einfügen

from cs50 import SQL

# Datenbankverbindung herstellen
db = SQL("sqlite:///meinedatenbank.db")

# DATEN LESEN (SELECT)
# db.execute gibt eine Liste von Dictionaries zurück
users = db.execute("SELECT * FROM users WHERE status = ?", "active")
for user in users:
    print(user["username"])

# DATEN SCHREIBEN (INSERT)
# WICHTIG: Immer Platzhalter (?) verwenden, um SQL-Injection zu verhindern!
username = request.form.get("username")
db.execute("INSERT INTO users (username) VALUES (?)", username)
Sicherheitshinweis: Übergeben Sie niemals Benutzereingaben direkt via f-Strings an SQL-Queries. Nutzen Sie immer die Platzhalter-Syntax (? oder :name), die von db.execute bereitgestellt wird.