Modèles de formulaire¶
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.
🌐 Traduction par IA et humains
Cette traduction a été réalisée par une IA guidée par des humains. 🤝
Elle peut contenir des erreurs d'interprétation du sens original, ou paraître peu naturelle, etc. 🤖
Vous pouvez améliorer cette traduction en nous aidant à mieux guider le LLM d'IA.
Vous pouvez utiliser des modèles Pydantic pour déclarer des champs de formulaire dans FastAPI.
Remarque
Pour utiliser les formulaires, installez d'abord python-multipart.
Ajoutez-le à votre projet :
$ uv add python-multipart
Remarque
Ceci est pris en charge depuis la version 0.113.0 de FastAPI. 🤓
Modèles Pydantic pour les formulaires¶
Vous avez simplement besoin de déclarer un modèle Pydantic avec les champs que vous souhaitez recevoir comme champs de formulaire, puis de déclarer le paramètre comme Form :
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 va extraire les données pour chaque champ à partir des données de formulaire de la requête et vous fournir le modèle Pydantic que vous avez défini.
Pour les cases à cocher HTML, déclarez des champs booléens avec une valeur par défaut de False.
Consultez les documents¶
Vous pouvez le vérifier dans l'interface des documents à /docs :
Interdire les champs de formulaire supplémentaires¶
Dans certains cas d'utilisation particuliers (probablement peu courants), vous pourriez vouloir restreindre les champs de formulaire à ceux déclarés dans le modèle Pydantic. Et interdire tout champ supplémentaire.
Remarque
Ceci est pris en charge depuis la version 0.114.0 de FastAPI. 🤓
Vous pouvez utiliser la configuration du modèle Pydantic pour forbid tout champ extra :
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
Si un client tente d'envoyer des données supplémentaires, il recevra une réponse d'erreur.
Par exemple, si le client essaie d'envoyer les champs de formulaire :
username:Rickpassword:Portal Gunextra:Mr. Poopybutthole
Il recevra une réponse d'erreur lui indiquant que le champ extra n'est pas autorisé :
{
"detail": [
{
"type": "extra_forbidden",
"loc": ["body", "extra"],
"msg": "Extra inputs are not permitted",
"input": "Mr. Poopybutthole"
}
]
}
Combiner des modèles de formulaire¶
Vous pouvez combiner plusieurs modèles de formulaire avec des paramètres Form individuels.
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}
Le client envoie name, tags et token comme champs de formulaire. Chaque modèle valide les champs de formulaire indépendamment.
La configuration extra de chaque modèle s'applique à tous les champs de formulaire, y compris les champs et les fichiers déclarés dans d'autres paramètres ou dépendances. Avec extra="forbid", tout champ extérieur à ce modèle est rejeté. Avec extra="allow", ces champs sont inclus comme données supplémentaires du modèle.
Si plusieurs déclarations utilisent le même nom de champ de formulaire, chacune valide la valeur de ce champ. Utilisez des types et des contraintes compatibles pour les champs partagés afin que le schéma OpenAPI puisse les décrire de manière cohérente.
Modèles de formulaire optionnels¶
Déclarez un modèle de formulaire avec | None et une valeur par défaut de None pour rendre le groupe optionnel.
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}
Si ni name ni age ne sont envoyés, profile vaut None. Si l'un des deux est envoyé, FastAPI valide le modèle et exige les deux champs. Une valeur vide soumise compte également comme un champ fourni.
Utiliser | None sans valeur par défaut laisse le paramètre obligatoire.
Les champs supplémentaires suivent la configuration extra du modèle. Les champs supplémentaires ignorés ne rendent pas le modèle présent.
Un modèle optionnel ne contenant que des cases à cocher non cochées est omis. Envoyez une valeur telle que enabled=false pour le fournir explicitement.
Unions optionnelles de modèles de formulaire¶
Vous pouvez également utiliser une union optionnelle de modèles.
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
Si aucun champ de formulaire n'est envoyé, contact vaut None. Envoyez kind=person avec name, ou kind=company avec company_name. Le discriminateur sélectionne le modèle à valider.
Combiner des unions de modèles de formulaire¶
Vous pouvez combiner des unions avec d'autres modèles de formulaire, des paramètres Form individuels et des paramètres File. Chaque union est validée indépendamment.
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}
Envoyez tous les champs dans le même formulaire. Par exemple, envoyez contact_type=person, name=Rick, notification_type=email, email=rick@example.com et token=secret.
Omettez les champs de notification pour laisser notification à None.
Modèles de formulaire et fichiers¶
Vous pouvez également combiner un modèle de formulaire avec des paramètres de fichier.
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}
Ici, le client envoie le champ name et le fichier avatar en utilisant multipart/form-data.
Résumer¶
Vous pouvez utiliser des modèles Pydantic pour déclarer des champs de formulaire dans FastAPI. 😎