DokuErweitert

Rezepte

Drei Dinge, die fast jede App benötigt, nämlich vollständige Dateien, die Sie kopieren können. Jeder Codeblock unten mit einem filename wird in ein neues Projekt geschrieben und von der Testsuite ausgeführt, sodass das, was Sie lesen, auch ausgeführt wird.

Sie verwenden einfache API-Handler; Die gleichen Funktionen funktionieren hinter einer Seite in jedem Modus.

Melden Sie sich mit einer Sitzung an

Ein Besucher gibt einen Namen und ein Passwort ein, der Server merkt sich diese in einem signierten Cookie und alles unter /api/account ist für alle anderen gesperrt.

Schalten Sie Sitzungen ein. Sie benötigen itsdangerous (uv add itsdangerous):

nexyconfig.py
from nexy.core.models import NexyConfigModel  class NexyConfig(NexyConfigModel):    useSession = {"secret_key": "change-me-in-production"}

An- und Abmelden:

src/routes/api/login.py
from pydantic import BaseModel from nexy.http import HTTPException, Request USERS = {"ada": "lovelace"}  class Credentials(BaseModel):    name: str    password: str  async def POST(request: Request, body: Credentials):    if USERS.get(body.name) != body.password:        raise HTTPException(status_code=401, detail="Wrong name or password")    request.session["user"] = body.name    return {"user": body.name}
src/routes/api/logout.py
from nexy.http import Request  async def POST(request: Request):    request.session.clear()    return {"signed_out": True}

Schützen Sie einen ganzen Ordner mit einem dependencies.py:

src/routes/api/account/dependencies.py
from nexy.http import HTTPException, Request  def current_user(request: Request) -> str:    if not request.session.get("user"):        raise HTTPException(status_code=401, detail="Sign in first")    return request.session["user"]  dependencies = [current_user]
src/routes/api/account/index.py
from nexy.http import Request  async def GET(request: Request):    return {"user": request.session["user"]}

Eine JSON-API mit Erstellen, Lesen und Löschen

Ein Speicher in einem Modul, eine Sammelroute und eine Artikelroute. Ersetzen Sie das Wörterbuch durch eine Datenbank, wenn die Daten einen Neustart überstehen müssen.

src/notes.py
from pydantic import BaseModel  class Note(BaseModel):    id: int    title: str  NOTES: dict[int, Note] = {}
src/routes/api/notes/index.py
from pydantic import BaseModel from src.notes import NOTES, Note  class NewNote(BaseModel):    title: str  async def GET() -> list[Note]:    return list(NOTES.values())  async def POST(body: NewNote) -> Note:    note = Note(id=max(NOTES, default=0) + 1, title=body.title)    NOTES[note.id] = note    return note
src/routes/api/notes/[id].py
from nexy.http import HTTPException from src.notes import NOTES, Note  async def GET(id: int) -> Note:    if id not in NOTES:        raise HTTPException(status_code=404, detail="No such note")    return NOTES[id]  async def DELETE(id: int) -> dict[str, bool]:    if NOTES.pop(id, None) is None:        raise HTTPException(status_code=404, detail="No such note")    return {"deleted": True}

Ein Körper, der nicht zu NewNote passt, wird mit 422 abgelehnt, bevor Ihr Code ausgeführt wird, und die Rückgabeanmerkung wird zur dokumentierten Antwort. Siehe Validierung und Fehler.

Erhalten Sie eine Datei

Uploads benötigen python-multipart (uv add python-multipart). Überprüfen Sie die Größe selbst und verwenden Sie niemals den Dateinamen des Clients als Pfad:

src/routes/api/upload.py
from pathlib import Path from nexy.http import HTTPException, UploadFile MAX_BYTES = 1_000_000  async def POST(file: UploadFile) -> dict[str, int | str]:    data = await file.read()    if len(data) > MAX_BYTES:        raise HTTPException(status_code=413, detail="File too large")    name = Path(file.filename or "upload").name    return {"name": name, "size": len(data)}

Path(...).name löscht alle Ordner, die der Client in den Namen eingegeben hat, z. B. ../../etc/passwd. Speichern Sie die Bytes unter einem von Ihnen generierten Namen, nicht unter diesem.

Nächste Schritte

Auf GitHub bearbeiten

Enter öffnet das Ergebnis, Esc schließt.