Zum Inhalt

Formularmodelle

AI coding agents

Use the official FastAPI skill for your installed version. Install it from your project directory:

uvx library-skills

See Develop with AI.

🌐 Übersetzung durch KI und Menschen

Diese Übersetzung wurde von KI erstellt, angeleitet von Menschen. đŸ€

Sie könnte Fehler enthalten, etwa MissverstĂ€ndnisse des ursprĂŒnglichen Sinns oder unnatĂŒrliche Formulierungen, usw. đŸ€–

Sie können diese Übersetzung verbessern, indem Sie uns helfen, die KI-LLM besser anzuleiten.

Englische Version

Sie können Pydantic-Modelle verwenden, um Formularfelder in FastAPI zu deklarieren.

Hinweis

Um Formulare zu verwenden, installieren Sie zuerst python-multipart.

FĂŒgen Sie es zu Ihrem Projekt hinzu:

$ uv add python-multipart

Hinweis

Dies wird seit FastAPI Version 0.113.0 unterstĂŒtzt. đŸ€“

Pydantic-Modelle fĂŒr Formulare

Sie mĂŒssen nur ein Pydantic-Modell mit den Feldern deklarieren, die Sie als Formularfelder erhalten möchten, und dann den Parameter als Form deklarieren:

from typing import Annotated

from fastapi import FastAPI, Form
from pydantic import BaseModel

app = FastAPI()


class FormData(BaseModel):
    username: str
    password: str


@app.post("/login/")
async def login(data: Annotated[FormData, Form()]):
    return data
đŸ€“ Other versions and variants

Tip

Prefer to use the Annotated version if possible.

from fastapi import FastAPI, Form
from pydantic import BaseModel

app = FastAPI()


class FormData(BaseModel):
    username: str
    password: str


@app.post("/login/")
async def login(data: FormData = Form()):
    return data

FastAPI wird die Daten fĂŒr jedes Feld aus den Formulardaten im Request extrahieren und Ihnen das von Ihnen definierte Pydantic-Modell ĂŒbergeben.

Deklarieren Sie fĂŒr HTML-Checkboxen boolesche Felder mit dem Defaultwert False.

Die Dokumentation testen

Sie können dies in der Dokumentations-UI unter /docs testen:

ZusÀtzliche Formularfelder verbieten

In einigen speziellen AnwendungsfÀllen (wahrscheinlich nicht sehr hÀufig) möchten Sie möglicherweise die Formularfelder auf nur diejenigen beschrÀnken, die im Pydantic-Modell deklariert sind. Und jegliche zusÀtzlichen Felder verbieten.

Hinweis

Dies wird seit FastAPI Version 0.114.0 unterstĂŒtzt. đŸ€“

Sie können Pydantics Modellkonfiguration verwenden, um jegliche extra-Felder auf forbid zu setzen:

from typing import Annotated

from fastapi import FastAPI, Form
from pydantic import BaseModel

app = FastAPI()


class FormData(BaseModel):
    username: str
    password: str
    model_config = {"extra": "forbid"}


@app.post("/login/")
async def login(data: Annotated[FormData, Form()]):
    return data
đŸ€“ Other versions and variants

Tip

Prefer to use the Annotated version if possible.

from fastapi import FastAPI, Form
from pydantic import BaseModel

app = FastAPI()


class FormData(BaseModel):
    username: str
    password: str
    model_config = {"extra": "forbid"}


@app.post("/login/")
async def login(data: FormData = Form()):
    return data

Wenn ein Client versucht, einige zusÀtzliche Daten zu senden, erhÀlt er eine Error-Response.

Zum Beispiel, wenn der Client versucht, folgende Formularfelder zu senden:

  • username: Rick
  • password: Portal Gun
  • extra: Mr. Poopybutthole

Er erhÀlt eine Error-Response, die ihm mitteilt, dass das Feld extra nicht erlaubt ist:

{
    "detail": [
        {
            "type": "extra_forbidden",
            "loc": ["body", "extra"],
            "msg": "Extra inputs are not permitted",
            "input": "Mr. Poopybutthole"
        }
    ]
}

Formularmodelle kombinieren

Sie können mehrere Formularmodelle mit einzelnen Form-Parametern kombinieren.

from typing import Annotated

from fastapi import FastAPI, Form
from pydantic import BaseModel

app = FastAPI()


class Profile(BaseModel):
    name: str


class Preferences(BaseModel):
    tags: list[str] = []


@app.post("/profiles/")
async def create_profile(
    profile: Annotated[Profile, Form()],
    preferences: Annotated[Preferences, Form()],
    token: Annotated[str, Form()],
):
    return {"profile": profile, "preferences": preferences, "token": token}
đŸ€“ Other versions and variants

Tip

Prefer to use the Annotated version if possible.

from fastapi import FastAPI, Form
from pydantic import BaseModel

app = FastAPI()


class Profile(BaseModel):
    name: str


class Preferences(BaseModel):
    tags: list[str] = []


@app.post("/profiles/")
async def create_profile(
    profile: Profile = Form(),
    preferences: Preferences = Form(),
    token: str = Form(),
):
    return {"profile": profile, "preferences": preferences, "token": token}

Der Client sendet name, tags und token als Formularfelder. Jedes Modell validiert die Formularfelder unabhÀngig.

Die extra-Konfiguration jedes Modells gilt fĂŒr alle Formularfelder, einschließlich der Felder und Dateien, die in anderen Parametern oder AbhĂ€ngigkeiten deklariert sind. Mit extra="forbid" wird jedes Feld außerhalb dieses Modells abgelehnt. Mit extra="allow" werden diese Felder als zusĂ€tzliche Felder im Modell aufgenommen.

Wenn mehrere Deklarationen denselben Formularfeldnamen verwenden, validiert jede den Wert dieses Feldes. Verwenden Sie kompatible Typen und EinschrĂ€nkungen fĂŒr gemeinsam genutzte Felder, damit das OpenAPI-Schema sie konsistent beschreiben kann.

Optionale Formularmodelle

Deklarieren Sie ein Formularmodell mit | None und dem Defaultwert None, um die Gruppe optional zu machen.

from typing import Annotated

from fastapi import FastAPI, Form
from pydantic import BaseModel

app = FastAPI()


class Profile(BaseModel):
    name: str
    age: int


@app.post("/profiles/")
async def create_profile(
    token: Annotated[str, Form()],
    profile: Annotated[Profile | None, Form()] = None,
):
    return {"token": token, "profile": profile}
đŸ€“ Other versions and variants

Tip

Prefer to use the Annotated version if possible.

from fastapi import FastAPI, Form
from pydantic import BaseModel

app = FastAPI()


class Profile(BaseModel):
    name: str
    age: int


@app.post("/profiles/")
async def create_profile(
    token: str = Form(),
    profile: Profile | None = Form(default=None),
):
    return {"token": token, "profile": profile}

Wenn weder name noch age gesendet wird, ist profile gleich None. Wenn eines der beiden gesendet wird, validiert FastAPI das Modell und erfordert beide Felder. Auch ein ĂŒbermittelter leerer Wert zĂ€hlt als Angabe eines Feldes.

Die Verwendung von | None ohne Defaultwert macht den Parameter weiterhin erforderlich.

ZusĂ€tzliche Felder folgen der extra-Konfiguration des Modells. Ignorierte zusĂ€tzliche Felder fĂŒhren nicht dazu, dass das Modell als vorhanden gilt.

Ein optionales Modell, das nur nicht aktivierte Checkboxen enthÀlt, wird weggelassen. Senden Sie einen Wert wie enabled=false, um es explizit anzugeben.

Optionale Unions von Formularmodellen

Sie können auch eine optionale Union von Modellen verwenden.

from typing import Annotated, Literal

from fastapi import FastAPI, Form
from pydantic import BaseModel

app = FastAPI()


class Person(BaseModel):
    kind: Literal["person"]
    name: str


class Company(BaseModel):
    kind: Literal["company"]
    company_name: str


@app.post("/contacts/")
async def create_contact(
    contact: Annotated[Person | Company | None, Form(discriminator="kind")] = None,
):
    return contact
đŸ€“ Other versions and variants

Tip

Prefer to use the Annotated version if possible.

from typing import Literal

from fastapi import FastAPI, Form
from pydantic import BaseModel

app = FastAPI()


class Person(BaseModel):
    kind: Literal["person"]
    name: str


class Company(BaseModel):
    kind: Literal["company"]
    company_name: str


@app.post("/contacts/")
async def create_contact(
    contact: Person | Company | None = Form(default=None, discriminator="kind"),
):
    return contact

Wenn keine Formularfelder gesendet werden, ist contact gleich None. Senden Sie kind=person mit name oder kind=company mit company_name. Der Diskriminator wÀhlt aus, welches Modell validiert werden soll.

Unions von Formularmodellen kombinieren

Sie können Unions mit anderen Formularmodellen, einzelnen Form-Parametern und File-Parametern kombinieren. Jede Union wird unabhÀngig validiert.

from typing import Annotated, Literal

from fastapi import FastAPI, Form
from pydantic import BaseModel

app = FastAPI()


class Person(BaseModel):
    contact_type: Literal["person"]
    name: str


class Company(BaseModel):
    contact_type: Literal["company"]
    company_name: str


class Email(BaseModel):
    notification_type: Literal["email"]
    email: str


class SMS(BaseModel):
    notification_type: Literal["sms"]
    phone: str


@app.post("/contacts/")
async def create_contact(
    contact: Annotated[Person | Company, Form(discriminator="contact_type")],
    token: Annotated[str, Form()],
    notification: Annotated[
        Email | SMS | None, Form(discriminator="notification_type")
    ] = None,
):
    return {"contact": contact, "notification": notification, "token": token}
đŸ€“ Other versions and variants

Tip

Prefer to use the Annotated version if possible.

from typing import Literal

from fastapi import FastAPI, Form
from pydantic import BaseModel

app = FastAPI()


class Person(BaseModel):
    contact_type: Literal["person"]
    name: str


class Company(BaseModel):
    contact_type: Literal["company"]
    company_name: str


class Email(BaseModel):
    notification_type: Literal["email"]
    email: str


class SMS(BaseModel):
    notification_type: Literal["sms"]
    phone: str


@app.post("/contacts/")
async def create_contact(
    contact: Person | Company = Form(discriminator="contact_type"),
    token: str = Form(),
    notification: Email | SMS | None = Form(
        default=None, discriminator="notification_type"
    ),
):
    return {"contact": contact, "notification": notification, "token": token}

Senden Sie alle Felder im selben Formular. Senden Sie beispielsweise contact_type=person, name=Rick, notification_type=email, email=rick@example.com und token=secret.

Lassen Sie die Benachrichtigungsfelder weg, damit notification gleich None bleibt.

Formularmodelle und Dateien

Sie können ein Formularmodell auch mit Dateiparametern kombinieren.

from typing import Annotated

from fastapi import FastAPI, Form, UploadFile
from pydantic import BaseModel

app = FastAPI()


class Profile(BaseModel):
    name: str


@app.post("/profiles/")
async def create_profile(profile: Annotated[Profile, Form()], avatar: UploadFile):
    return {"profile": profile, "filename": avatar.filename}
đŸ€“ Other versions and variants

Tip

Prefer to use the Annotated version if possible.

from fastapi import FastAPI, File, Form, UploadFile
from pydantic import BaseModel

app = FastAPI()


class Profile(BaseModel):
    name: str


@app.post("/profiles/")
async def create_profile(profile: Profile = Form(), avatar: UploadFile = File()):
    return {"profile": profile, "filename": avatar.filename}

Hier sendet der Client das Feld name und die Datei avatar mittels multipart/form-data.

Zusammenfassung

Sie können Pydantic-Modelle verwenden, um Formularfelder in FastAPI zu deklarieren. 😎