Recebendo Dados de Requisição como Objeto de Classe - 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
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
<!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
Configurando p Backend
O arquivo main.py
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
BaseModel
name
age
O endpoint /hello
Person
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
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
age
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);