Modelos de Formulários¶
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.
🌐 Tradução por IA e humanos
Esta tradução foi feita por IA orientada por humanos. 🤝
Ela pode conter erros de interpretação do significado original ou soar pouco natural, etc. 🤖
Você pode melhorar esta tradução ajudando-nos a orientar melhor o LLM de IA.
Você pode utilizar Modelos Pydantic para declarar campos de formulários no FastAPI.
Nota
Para utilizar formulários, instale primeiramente o python-multipart.
Adicione-o ao seu projeto:
$ uv add python-multipart
Nota
Isto é suportado desde a versão 0.113.0 do FastAPI. 🤓
Modelos Pydantic para Formulários¶
Você precisa apenas declarar um modelo Pydantic com os campos que deseja receber como campos de formulários, e então declarar o parâmetro como um 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
O FastAPI irá extrair as informações para cada campo dos dados do formulário na requisição e dar para você o modelo Pydantic que você definiu.
Para caixas de seleção HTML, declare campos booleanos com o valor padrão False.
Confira a Documentação¶
Você pode verificar na UI de documentação em /docs:
Proíba Campos Extras de Formulários¶
Em alguns casos de uso especiais (provavelmente não muito comum), você pode desejar restringir os campos do formulário para aceitar apenas os declarados no modelo Pydantic. E proibir qualquer campo extra.
Nota
Isso é suportado desde a versão 0.114.0 do FastAPI. 🤓
Você pode utilizar a configuração de modelo do Pydantic para definir forbid para qualquer campo 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
Caso um cliente tente enviar informações adicionais, ele receberá um retorno de erro.
Por exemplo, se o cliente tentar enviar os campos de formulário:
username:Rickpassword:Portal Gunextra:Mr. Poopybutthole
Ele receberá um retorno de erro informando-o que o campo extra não é permitido:
{
"detail": [
{
"type": "extra_forbidden",
"loc": ["body", "extra"],
"msg": "Extra inputs are not permitted",
"input": "Mr. Poopybutthole"
}
]
}
Combine Modelos de Formulários¶
Você pode combinar vários modelos de formulários com parâmetros Form individuais.
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}
O cliente envia name, tags e token como campos de formulário. Cada modelo valida os campos do formulário de forma independente.
A configuração extra de cada modelo se aplica a todos os campos do formulário, incluindo campos e arquivos declarados em outros parâmetros ou dependências. Com extra="forbid", qualquer campo fora desse modelo é rejeitado. Com extra="allow", esses campos são incluídos como extras do modelo.
Se várias declarações usarem o mesmo nome de campo de formulário, cada uma validará o valor desse campo. Use tipos e restrições compatíveis para campos compartilhados, para que o esquema OpenAPI possa descrevê-los de forma consistente.
Modelos de Formulários Opcionais¶
Declare um modelo de formulário com | None e um valor padrão None para tornar o grupo opcional.
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}
Se nem name nem age forem enviados, profile será None. Se qualquer um deles for enviado, o FastAPI validará o modelo e exigirá ambos os campos. Um valor vazio enviado também conta como fornecimento de um campo.
Usar | None sem um valor padrão ainda torna o parâmetro obrigatório.
Campos extras seguem a configuração extra do modelo. Extras ignorados não fazem com que o modelo seja considerado presente.
Um modelo opcional que contenha apenas caixas de seleção desmarcadas é omitido. Envie um valor como enabled=false para fornecê-lo explicitamente.
Uniões Opcionais de Modelos de Formulários¶
Você também pode usar uma união opcional de modelos.
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
Se nenhum campo de formulário for enviado, contact será None. Envie kind=person com name, ou kind=company com company_name. O discriminador seleciona qual modelo validar.
Combine Uniões de Modelos de Formulários¶
Você pode combinar uniões com outros modelos de formulários, parâmetros Form individuais e parâmetros File. Cada união é validada de forma independente.
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}
Envie todos os campos no mesmo formulário. Por exemplo, envie contact_type=person, name=Rick, notification_type=email, email=rick@example.com e token=secret.
Omita os campos de notificação para deixar notification como None.
Modelos de Formulários e Arquivos¶
Você também pode combinar um modelo de formulário com parâmetros de arquivo.
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}
Aqui, o cliente envia o campo name e o arquivo avatar usando multipart/form-data.
Resumo¶
Você pode utilizar modelos Pydantic para declarar campos de formulários no FastAPI. 😎