Recebendo Dados de Requisição como Objeto de Classe em FastAPI
O FastAPI permite mapear os dados de uma requisição diretamente para objetos de classes definidas pelo desenvolvedor. Essas classes devem herdar de pydantic.BaseModel
e são projetadas para modelar os dados esperados na requisição.
Estrutura do Projeto
Para exemplificar, criaremos uma API que recebe um objeto contendo o nome e a idade de uma pessoa e retorna uma mensagem de boas-vindas com esses dados. A estrutura do projeto será organizada da seguinte forma:
. ├── public │ └── index.html ├── main.py
Interface Web
Para testar a API, criaremos uma interface web que simula um cliente enviando dados ao servidor. O arquivo index.html
conterá:
<!DOCTYPE html>
<html>
<head>
<title>FastAPI Demo</title>
<meta charset="utf-8" />
</head>
<body>
<div id="message"></div>
<p>
Digite seu nome: <br />
<input name="username" id="username" />
</p>
<p>
Digite sua idade: <br />
<input name="userage" id="userage" type="number" />
</p>
<button onclick="send()">Enviar</button>
<script>
async function send() {
const username = document.getElementById("username").value;
const userage = document.getElementById("userage").value;
const response = await fetch("/hello", {
method: "POST",
headers: { Accept: "application/json", "Content-Type": "application/json" },
body: JSON.stringify({
name: username,
age: userage,
}),
});
if (response.ok) {
const data = await response.json();
document.getElementById("message").textContent = data.message;
} else {
console.log(response);
}
}
</script>
</body>
</html>
Esse formulário captura os dados inseridos pelo usuário e os envia para o endpoint /hello
via uma requisição POST.
Configurando p Backend
O arquivo main.py
conterá a definição da API:
from fastapi import FastAPI
from fastapi.responses import FileResponse
from pydantic import BaseModel
class Person(BaseModel):
name: str
age: int
app = FastAPI()
@app.get("/")
def root():
return FileResponse("public/index.html")
@app.post("/hello")
def hello(person: Person):
return {"message": f"Olá, {person.name}, sua idade é {person.age}"}
A classe Person
é uma subclasse de BaseModel
e define os campos name
e age
que serão mapeados a partir dos dados enviados pelo cliente.
O endpoint /hello
recebe um objeto do tipo Person
e retorna uma mensagem de boas-vindas contendo o nome e a idade da pessoa.
Atributos Opcionais
No FastAPI, é possível tornar alguns atributos opcionais, atribuindo-lhes None como valor padrão:
from fastapi import FastAPI
from fastapi.responses import FileResponse
from pydantic import BaseModel
class Person(BaseModel):
name: str
age: int | None = None
app = FastAPI()
@app.get("/")
def root():
return FileResponse("public/index.html")
@app.post("/hello")
def hello(person: Person):
if person.age is None:
return {"message": f"Olá, {person.name}"}
else:
return {"message": f"Olá, {person.name}, sua idade é {person.age}"}
Configuração Detalhada com Field
O módulo pydantic
permite configurar validações e valores padrão com Field
:
from fastapi import FastAPI
from fastapi.responses import FileResponse
from pydantic import BaseModel, Field
class Person(BaseModel):
name: str = Field(default="Indefinido", min_length=3, max_length=20)
age: int = Field(default=18, ge=18, lt=111)
app = FastAPI()
@app.get("/")
def root():
return FileResponse("public/index.html")
@app.post("/hello")
def hello(person: Person):
return {"message": f"Olá, {person.name}, sua idade é {person.age}"}
Nesse exemplo, o campo name
deve ter entre 3 e 20 caracteres e o campo age
deve ser maior ou igual a 18 e menor que 111.
Trabalhando com Listas
É possível receber listas de objetos:
from fastapi import FastAPI
from pydantic import BaseModel
class Person(BaseModel):
name: str
age: int
app = FastAPI()
@app.post("/hello")
def hello(people: list[Person]):
return {"message": people}
Envio de exemplo com JavaScript:
const response = await fetch("/hello", {
method: "POST",
headers: { Accept: "application/json", "Content-Type": "application/json" },
body: JSON.stringify([
{ name: "Tom", age: 38 },
{ name: "Bob", age: 41 },
{ name: "Sam", age: 25 },
]),
});
const data = await response.json();
console.log(data);
Modelos Aninhados
Modelos podem conter outros modelos:
from fastapi import FastAPI
from pydantic import BaseModel
class Company(BaseModel):
name: str
class Person(BaseModel):
name: str
company: Company
app = FastAPI()
@app.post("/hello")
def hello(person: Person):
return {"message": f"{person.name} trabalha na empresa {person.company.name}"}
Envio de exemplo com JavaScript:
const response = await fetch("/hello", {
method: "POST",
headers: { Accept: "application/json", "Content-Type": "application/json" },
body: JSON.stringify({
name: "Tom",
company: { name: "Google" },
}),
});
const data = await response.json();
console.log(data);
Documentação oficial: