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:

  • GET: Recuperar dados.

  • POST: Adicionar dados.

  • PUT: Atualizar dados.

  • DELETE: Remover dados.

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, começamos definindo a estrutura dos dados. Criamos a classe Person para representar cada usuário:

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 possui:

  • name: Nome do usuário.

  • age: Idade do usuário.

  • id: Identificador único gerado automaticamente usando uuid.uuid4().

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

  1. Rota raiz: Serve um arquivo HTML que permite a interação com a API:

    @app.get("/")
    async def main():
        return FileResponse("public/index.html")
    
  2. Listar todos os usuários: Retorna todos os usuários registrados:

    @app.get("/api/users")
    def get_people():
        return people
    
  3. 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
    
  4. 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
      
  5. 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
    
  6. 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 contém o seguinte código:

<!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.

Interação de JavaScript com FastAPI
Política de Privacidade

Copyright © www.programicio.com Todos os direitos reservados

É proibida a reprodução do conteúdo desta página sem autorização prévia do autor.

Contato: programicio@gmail.com