10 Minuten vom ersten Codezeile zur Live-Bereitstellung: Ein super schneller FastAPI-Blog-Kurs
Wenhao Wang
Dev Intern · Leapcell

Dies ist ein Crashkurs für FastAPI. In diesem Tutorial verwenden wir Python FastAPI, um einen Blog zu erstellen, von der ersten Codezeile bis zur Bereitstellung, in nur wenigen einfachen Schritten und unter 10 Minuten.
Der Grund, warum es so schnell geht, ist, dass dieses Tutorial nicht jedes Konzept im Detail behandelt. Stattdessen führt es Sie direkt zum Erstellen eines fertigen Produkts. Ich glaube, dass die Änderung eines bestehenden Produkts nach eigenen Ideen der effizienteste Weg ist, ein neues Framework zu meistern.
Dieser Blog ist ein reines Backend-Logik- und Rendering-Projekt, das einen gängigen Technologie-Stack für die Python-Webentwicklung verwendet:
- FastAPI + Uvicorn
- PostgreSQL
- SQLModel: Für die Interaktion mit der Datenbank aus dem Code.
- Jinja2: Eine Template-Engine zum Rendern von Frontend-Seiten.
Ohne weitere Umschweife legen wir los:
1. Projekt initialisieren
Führen Sie die folgenden Befehle in Ihrem Terminal aus:
# 1. Projektverzeichnis erstellen und betreten mkdir fastapi-personal-blog && cd fastapi-personal-blog # 2. Virtuelle Umgebung erstellen und aktivieren python -m venv venv source venv/bin/activate
Erstellen Sie eine Datei requirements.txt
und fügen Sie die folgenden Abhängigkeiten hinzu:
# requirements.txt fastapi uvicorn[standard] sqlmodel psycopg2-binary jinja2 python-dotenv python-multipart
Installieren Sie sie dann:
pip install -r requirements.txt
2. Verbindung zu einer PostgreSQL-Datenbank herstellen
Als Nächstes integrieren wir eine PostgreSQL-Datenbank.
Datenbank einrichten
Um das Tutorial zu beschleunigen, überspringen wir den Schritt der lokalen Installation und Einrichtung einer Datenbank. Stattdessen stellen wir direkt eine Online-Datenbank bereit.
Wir können mit einem Klick auf Leapcell eine kostenlose Datenbank erstellen.
Nachdem Sie ein Konto auf der Website registriert haben, klicken Sie auf "Create Database".
Geben Sie einen Datenbanknamen ein, wählen Sie eine Bereitstellungsregion und Sie können die PostgreSQL-Datenbank erstellen.
Auf der neu erscheinenden Seite finden Sie die Informationen, die zum Verbinden mit der Datenbank benötigt werden. Am unteren Rand ist ein Bedienfeld vorhanden, mit dem Sie die Datenbank direkt auf der Webseite lesen und ändern können.
In den Verbindungsinformationen auf der neuen Seite finden Sie den Connection String. Wir werden ihn bald verwenden.
Datenbankverbindung konfigurieren
Erstellen Sie eine Datei .env
im Stammverzeichnis des Projekts, um sensible Verbindungsinformationen zu speichern. Fügen Sie die von Leapcell erhaltene URL ein.
# .env DATABASE_URL="postgresql://user:password@host:port/dbname"
Erstellen Sie als Nächstes eine Datei database.py
, um die Datenbankverbindung zu verwalten:
# database.py import os from sqlmodel import create_engine, SQLModel, Session from dotenv import load_dotenv load_dotenv() DATABASE_URL = os.getenv("DATABASE_URL") engine = create_engine(DATABASE_URL) def create_db_and_tables(): SQLModel.metadata.create_all(engine) def get_session(): with Session(engine) as session: yield session
3. Das Post-Modul erstellen
Als Nächstes implementieren wir die Logik, die mit Blog-Posts zusammenhängt.
Erstellen Sie eine Datei models.py
im Stammverzeichnis des Projekts, um das Datenmodell zu definieren.
# models.py import uuid from datetime import datetime from typing import Optional from sqlmodel import Field, SQLModel class Post(SQLModel, table=True): id: Optional[uuid.UUID] = Field(default_factory=uuid.uuid4, primary_key=True) title: str content: str createdAt: datetime = Field(default_factory=datetime.utcnow, nullable=False)
SQLModel ordnet diese Klasse automatisch einer post
-Tabelle in der Datenbank zu. Die Funktion create_db_and_tables
stellt sicher, dass diese Tabelle beim Start der Anwendung erstellt wird, sodass keine manuellen SQL-Ausführungen erforderlich sind.
4. Jinja2 für Web-Rendering einrichten
Richten Sie Jinja2 zum Rendern der HTML-Website ein.
Verzeichnisstruktur erstellen
Erstellen Sie Ordner templates
und public
im Stammverzeichnis des Projekts. Der Ordner templates
speichert HTML-Dateien, und der Ordner public
speichert statische Assets wie CSS und JavaScript.
Die endgültige Projektstruktur wird wie folgt aussehen:
- fastapi-personal-blog
- templates
- public
- .env
- database.py
- models.py
- requirements.txt
Frontend-Seiten implementieren
Erstellen Sie die folgenden Dateien im Ordner templates
:
-
_header.html
(wiederverwendbarer Header)<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>{{ title }}</title> <link rel="stylesheet" href="/static/css/style.css" /> </head> <body> <header> <h1><a href="/">My Blog</a></h1> <a href="/posts/new" class="new-post-btn">New Post</a> </header> <main></main> </body> </html>
-
_footer.html
(wiederverwendbarer Footer)</main> <footer> <p>© 2025 My Blog</p> </footer> </body> </html>
-
index.html
(Blog-Homepage){% include "_header.html" %} <div class="post-list"> {% for post in posts %} <article class="post-item"> <h2><a href="/posts/{{ post.id }}">{{ post.title }}</a></h2> <p>{{ post.content[:150] }}...</p> <small>{{ post.createdAt.strftime('%Y-%m-%d') }}</small> </article> {% endfor %} </div> {% include "_footer.html" %}
-
post.html
(Post-Detailseite){% include "_header.html" %} <article class="post-detail"> <h1>{{ post.title }}</h1> <small>{{ post.createdAt.strftime('%Y-%m-%d') }}</small> <div class="post-content">{{ post.content | replace('
', '<br />') | safe }}</div>
</article> <a href="/" class="back-link">← Back to Home</a> {% include "_footer.html" %} ```-
new-post.html
(Seite für neuen Beitrag){% include "_header.html" %} <form action="/posts" method="POST" class="post-form"> <div class="form-group"> <label for="title">Title</label> <input type="text" id="title" name="title" required /> </div> <div class="form-group"> <label for="content">Content</label> <textarea id="content" name="content" rows="10" required></textarea> </div> <button type="submit">Submit</button> </form> {% include "_footer.html" %}
CSS-Stile hinzufügen
Erstellen Sie im Verzeichnis public
einen Ordner css
und darin eine Datei style.css
. Die Stile sind mit dem Originalartikel identisch.
/* public/css/style.css */ body { font-family: sans-serif; line-height: 1.6; margin: 0; background-color: #f4f4f4; color: #333; } header { background: #333; color: #fff; padding: 1rem; display: flex; justify-content: space-between; align-items: center; } header a { color: #fff; text-decoration: none; } main { max-width: 800px; margin: 2rem auto; padding: 1rem; background: #fff; border-radius: 5px; } .post-item { margin-bottom: 2rem; border-bottom: 1px solid #eee; padding-bottom: 1rem; } .post-item h2 a { text-decoration: none; color: #333; } .post-detail .post-content { margin-top: 1rem; } .new-post-btn { background: #5cb85c; padding: 0.5rem 1rem; border-radius: 5px; } .post-form .form-group { margin-bottom: 1rem; } .post-form label { display: block; margin-bottom: 0.5rem; } .post-form input, .post-form textarea { width: 100%; padding: 0.5rem; } .post-form button { background: #337ab7; color: #fff; padding: 0.7rem 1.5rem; border: none; cursor: pointer; } footer p { text-align: center; }
5. Hauptanwendungslogik schreiben
Zum Schluss erstellen Sie eine Datei main.py
im Stammverzeichnis des Projekts. Diese Datei ist der Einstiegspunkt für die gesamte Anwendung und integriert die Datenbank-, Routing- und Template-Logik.
# main.py import uuid from contextlib import asynccontextmanager from fastapi import FastAPI, Request, Depends, Form from fastapi.responses import HTMLResponse, RedirectResponse from fastapi.staticfiles import StaticFiles from fastapi.templating import Jinja2Templates from sqlmodel import Session, select from database import create_db_and_tables, get_session from models import Post # Erstellt auf Anwendungsstart Datenbanktabellen @asynccontextmanager async def lifespan(app: FastAPI): print("Creating tables..") create_db_and_tables() yield app = FastAPI(lifespan=lifespan) # Hängt das Static-Dateien-Verzeichnis ein app.mount("/static", StaticFiles(directory="public"), name="static") # Richtet das Jinja2-Templates-Verzeichnis ein templates = Jinja2Templates(directory="templates") @app.get("/", response_class=HTMLResponse) def root(): # Leitet den Root-Pfad zur Post-Liste um return RedirectResponse(url="/posts", status_code=302) @app.get("/posts", response_class=HTMLResponse) def get_all_posts(request: Request, session: Session = Depends(get_session)): # Fragt alle Posts ab, sortiert nach Erstellungsdatum absteigend statement = select(Post).order_by(Post.createdAt.desc()) posts = session.exec(statement).all() return templates.TemplateResponse("index.html", {"request": request, "posts": posts}) @app.get("/posts/new", response_class=HTMLResponse) def new_post_form(request: Request): # Zeigt die Formularseite zum Erstellen eines neuen Posts an return templates.TemplateResponse("new-post.html", {"request": request, "title": "New Post"}) @app.post("/posts", response_class=HTMLResponse) def create_post( title: str = Form(...), content: str = Form(...), session: Session = Depends(get_session) ): # Empfängt Daten aus dem Formular und erstellt einen neuen Beitrag new_post = Post(title=title, content=content) session.add(new_post) session.commit() return RedirectResponse(url="/posts", status_code=302) @app.get("/posts/{post_id}", response_class=HTMLResponse) def get_post_by_id(request: Request, post_id: uuid.UUID, session: Session = Depends(get_session)): # Fragt einen einzelnen Beitrag nach ID ab und zeigt ihn an post = session.get(Post, post_id) return templates.TemplateResponse("post.html", {"request": request, "post": post, "title": post.title})
6. Den Blog ausführen
Zu diesem Zeitpunkt ist Ihre Blog-Entwicklung abgeschlossen. Führen Sie den folgenden Befehl im Terminal aus, um den Blog zu starten:
uvicorn main:app --reload
Der Parameter --reload
startet den Server beim Ändern des Codes automatisch neu, was für Entwicklung und Debugging praktisch ist.
Öffnen Sie http://localhost:8000
in Ihrem Browser, um die Homepage Ihres Blogs anzuzeigen. Sie können einen neuen Beitrag erstellen, um alle Funktionen zu testen!
7. Den Blog online bereitstellen
Jetzt fragen Sie sich vielleicht, wie kann ich die von mir erstellte Website anderen zeigen, damit jeder darauf zugreifen kann?
Erinnern Sie sich an Leapcell, das wir zuvor zur Erstellung der Datenbank verwendet haben? Leapcell kann mehr als nur Datenbanken erstellen; es ist auch eine Web-App-Hosting-Plattform, die Projekte in verschiedenen Sprachen und Frameworks hosten kann, einschließlich FastAPI.
Befolgen Sie die nachstehenden Schritte:
- Commiten Sie Ihr Projekt auf GitHub. Sie können die offizielle Dokumentation von GitHub für die Schritte konsultieren. Leapcell wird den Code später aus Ihrem GitHub-Repository ziehen.
- Klicken Sie auf der Leapcell-Seite auf "Create Service".
- Nachdem Sie Ihr FastAPI-Repository ausgewählt haben, sehen Sie, dass Leapcell die notwendigen Konfigurationen automatisch ausgefüllt hat.
- Sie müssen immer noch die Umgebungsvariablen selbst ausfüllen. Setzen Sie den
DATABASE_URL
auf denselben Wert wie in Ihrer.env
-Datei. - Bereitstellungs-Homepage. Hier sehen wir, dass Leapcell eine Domain bereitgestellt hat. Dies ist die Online-Adresse Ihres Blogs.
Jetzt können Sie diesen Link mit Ihren Freunden teilen, und jeder kann Ihren Blog online sehen!