Criando uma API - FastAPI
Neste tema, exploramos como criar uma API Web em estilo REST usando FastAPI. O estilo REST utiliza métodos HTTP específicos para interagir com o servidor, cada qual responsável por uma ação distinta:
: Recuperar dados.GET
: Adicionar dados.POST
: Atualizar dados.PUT
: Remover dados.DELETE
O FastAPI oferece suporte direto para esses métodos. Vamos implementar uma API simples para gerenciar uma lista de usuários, cobrindo todas essas operações.
Estrutura do Projeto
A estrutura do projeto será organizada da seguinte forma:
. ├── public │ └── index.html ├── main.py
Servidor
No arquivo main.py
import uuid
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
self.id = str(uuid.uuid4())
Cada instância de Person
: Nome do usuário.name
: Idade do usuário.age
: Identificador único gerado automaticamente usando uuid.uuid4().id
Para simular um banco de dados, criamos uma lista:
people = [Person("Tom", 38), Person("Bob", 42), Person("Sam", 28)]
E para buscar usuários na lista, definimos a função auxiliar find_person
def find_person(id):
for person in people:
if person.id == id:
return person
return None
Com o banco de dados simulado pronto, configuramos a aplicação FastAPI:
from fastapi import FastAPI, Body, status
from fastapi.responses import JSONResponse, FileResponse
app = FastAPI()
Definição das Rotas
Rota raiz: Serve um arquivo HTML que permite a interação com a API:
@app.get("/") async def main(): return FileResponse("public/index.html")
Listar todos os usuários: Retorna todos os usuários registrados:
@app.get("/api/users") def get_people(): return people
Buscar um usuário por ID: Retorna um usuário específico ou um erro se ele não for encontrado:
@app.get("/api/users/{id}") def get_person(id): person = find_person(id) if person is None: return JSONResponse( status_code=status.HTTP_404_NOT_FOUND, content={"message": "Usuário não encontrado"} ) return person
Criar um novo usuário: Adiciona um usuário com base nos dados enviados no corpo da requisição:
@app.post("/api/users") def create_person(data=Body()): person = Person(data["name"], data["age"]) people.append(person) return person
Editar um usuário existente: Atualiza as informações de um usuário já registrado:
@app.put("/api/users") def edit_person(data=Body()): person = find_person(data["id"]) if person is None: return JSONResponse( status_code=status.HTTP_404_NOT_FOUND, content={"message": "Usuário não encontrado"} ) person.name = data["name"] person.age = data["age"] return person
Excluir um usuário: Remove um usuário da lista pelo ID:
@app.delete("/api/users/{id}") def delete_person(id): person = find_person(id) if person is None: return JSONResponse( status_code=status.HTTP_404_NOT_FOUND, content={"message": "Usuário não encontrado"} ) people.remove(person) return person
O código completo do arquivo main.py
import uuid
from fastapi import FastAPI, Body, status
from fastapi.responses import JSONResponse, FileResponse
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
self.id = str(uuid.uuid4())
people = [Person("Tom", 38), Person("Bob", 42), Person("Sam", 28)]
def find_person(id):
for person in people:
if person.id == id:
return person
return None
app = FastAPI()
@app.get("/")
async def main():
return FileResponse("public/index.html")
@app.get("/api/users")
def get_people():
return people
@app.get("/api/users/{id}")
def get_person(id):
person = find_person(id)
if person is None:
return JSONResponse(
status_code=status.HTTP_404_NOT_FOUND,
content={"message": "Usuário não encontrado"}
)
return person
@app.post("/api/users")
def create_person(data=Body()):
person = Person(data["name"], data["age"])
people.append(person)
return person
@app.put("/api/users")
def edit_person(data=Body()):
person = find_person(data["id"])
if person is None:
return JSONResponse(
status_code=status.HTTP_404_NOT_FOUND,
content={"message": "Usuário não encontrado"}
)
person.name = data["name"]
person.age = data["age"]
return person
@app.delete("/api/users/{id}")
def delete_person(id):
person = find_person(id)
if person is None:
return JSONResponse(
status_code=status.HTTP_404_NOT_FOUND,
content={"message": "Usuário não encontrado"}
)
people.remove(person)
return person
Cliente
O cliente é um arquivo HTML que utiliza JavaScript para interagir com a API. Ele exibe uma tabela de usuários, permite adicionar, editar e excluir registros. A lógica principal está nas funções JavaScript que utilizam a API para realizar operações.
O arquivo index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Gerenciamento de Usuários</title>
<style>
td { padding: 5px; }
button { margin: 5px; }
</style>
</head>
<body>
<h2>Lista de Usuários</h2>
<div>
<input type="hidden" id="userId" />
<p>
Nome:<br/>
<input id="userName" />
</p>
<p>
Idade:<br />
<input id="userAge" type="number" />
</p>
<p>
<button id="saveBtn">Salvar</button>
<button id="resetBtn">Limpar</button>
</p>
</div>
<table>
<thead>
<tr>
<th>Nome</th>
<th>Idade</th>
<th>Ações</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<script>
// Buscar todos os usuários
async function getUsers() {
const response = await fetch("/api/users", {
method: "GET",
headers: { "Accept": "application/json" }
});
if (response.ok) {
const users = await response.json();
const rows = document.querySelector("tbody");
rows.innerHTML = ""; // Limpa a tabela antes de preenchê-la
users.forEach(user => rows.append(row(user)));
}
}
// Buscar um único usuário pelo ID
async function getUser(id) {
const response = await fetch(`/api/users/${id}`, {
method: "GET",
headers: { "Accept": "application/json" }
});
if (response.ok) {
const user = await response.json();
document.getElementById("userId").value = user.id;
document.getElementById("userName").value = user.name;
document.getElementById("userAge").value = user.age;
} else {
const error = await response.json();
console.log(error.message);
}
}
// Adicionar um novo usuário
async function createUser(userName, userAge) {
const response = await fetch("/api/users", {
method: "POST",
headers: {
"Accept": "application/json",
"Content-Type": "application/json"
},
body: JSON.stringify({
name: userName,
age: parseInt(userAge, 10)
})
});
if (response.ok) {
const user = await response.json();
document.querySelector("tbody").append(row(user));
} else {
const error = await response.json();
console.log(error.message);
}
}
// Editar um usuário existente
async function editUser(userId, userName, userAge) {
const response = await fetch("/api/users", {
method: "PUT",
headers: {
"Accept": "application/json",
"Content-Type": "application/json"
},
body: JSON.stringify({
id: userId,
name: userName,
age: parseInt(userAge, 10)
})
});
if (response.ok) {
const user = await response.json();
document.querySelector(`tr[data-rowid='${user.id}']`).replaceWith(row(user));
} else {
const error = await response.json();
console.log(error.message);
}
}
// Remover um usuário
async function deleteUser(id) {
const response = await fetch(`/api/users/${id}`, {
method: "DELETE",
headers: { "Accept": "application/json" }
});
if (response.ok) {
const user = await response.json();
document.querySelector(`tr[data-rowid='${user.id}']`).remove();
} else {
const error = await response.json();
console.log(error.message);
}
}
// Limpar o formulário
function reset() {
document.getElementById("userId").value = "";
document.getElementById("userName").value = "";
document.getElementById("userAge").value = "";
}
// Criar uma linha na tabela para exibir o usuário
function row(user) {
const tr = document.createElement("tr");
tr.setAttribute("data-rowid", user.id);
const nameTd = document.createElement("td");
nameTd.append(user.name);
tr.append(nameTd);
const ageTd = document.createElement("td");
ageTd.append(user.age);
tr.append(ageTd);
const actionsTd = document.createElement("td");
const editButton = document.createElement("button");
editButton.append("Editar");
editButton.addEventListener("click", () => getUser(user.id));
actionsTd.append(editButton);
const deleteButton = document.createElement("button");
deleteButton.append("Excluir");
deleteButton.addEventListener("click", () => deleteUser(user.id));
actionsTd.append(deleteButton);
tr.append(actionsTd);
return tr;
}
// Configurar os eventos dos botões
document.getElementById("resetBtn").addEventListener("click", reset);
document.getElementById("saveBtn").addEventListener("click", async () => {
const id = document.getElementById("userId").value;
const name = document.getElementById("userName").value;
const age = document.getElementById("userAge").value;
if (!id) {
await createUser(name, age);
} else {
await editUser(id, name, age);
}
reset();
});
// Carregar os usuários ao abrir a página
getUsers();
</script>
</body>
</html>
Neste arquivo, a tabela de usuários é preenchida com os dados obtidos da API. As funções JavaScript permitem adicionar, editar e excluir usuários, além de limpar o formulário.