Guia Completo para Criar sua Primeira API Rest com FastAPI

Aprenda a criar um projeto FastAPI com SQLAlchemy e um banco de dados SQLite para gerenciar um sistema básico de newsletter. Este guia aborda desde a inscrição e o cancelamento até a recuperação da lista de inscritos, facilitando o desenvolvimento de aplicações web modernas e eficientes. Ideal para quem busca soluções rápidas e práticas no desenvolvimento web com Python.

Criando um Projeto FastAPI com SQLAlchemy e Ambiente Virtual

Para iniciar, crie um diretório para o seu projeto FastAPI. Em seguida, configure um ambiente virtual para isolar as dependências do projeto. Utilize o seguinte comando pip para instalar as bibliotecas necessárias:

pip install fastapi[standard] uvicorn sqlalchemy aiomysql pydantic_settings

Cada biblioteca desempenha um papel crucial:

  • fastapi[standard]: Instala o FastAPI com dependências extras para funcionalidade completa.
  • uvicorn: Servidor ASGI para executar aplicações FastAPI de forma eficiente.
  • sqlalchemy: ORM para interagir com bancos de dados relacionais usando Python.
  • aiomysql: Driver MySQL assíncrono para SQLAlchemy, habilitando operações assíncronas no banco de dados.
  • pydantic_settings: Gerencia as configurações da aplicação usando arquivos .env e variáveis de ambiente com Pydantic.

Após a instalação, gere um arquivo requirements.txt para registrar todas as dependências:

pip freeze > requirements.txt

A estrutura do projeto deverá ser organizada da seguinte forma:

meu_projeto_fastapi/
├── main.py
├── database/
│   ├── config.py
│   ├── database.py
├── newsletter/
│   ├── models.py
│   ├── routes.py
│   ├── schemas.py
│   ├── utils.py
├── .env
├── requirements.txt
├── venv/ (ambiente virtual)
├── vercel.json
├── .gitignore
└── README.md

Detalhando os Arquivos do Projeto FastAPI com SQLAlchemy

Cada arquivo no projeto tem uma função específica. O arquivo main.py é o ponto de entrada da aplicação, onde a instância FastAPI é criada e as rotas são definidas. Já os arquivos dentro da pasta database são responsáveis pela configuração e gerenciamento do banco de dados, enquanto os arquivos em newsletter definem os modelos, rotas e esquemas para o sistema de newsletter.

O arquivo .env contém as variáveis de ambiente, requirements.txt lista as dependências do projeto, e vercel.json é usado para configurar o deploy na plataforma Vercel. Os arquivos .gitignore e README.md são para controle de versão e documentação, respectivamente.

O arquivo main.py é crucial para o funcionamento do FastAPI, pois é onde a aplicação é inicializada, as rotas são definidas e o servidor Uvicorn é configurado para executar a aplicação.

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from database.database import get_db , engine , Base
import os
import uvicorn
from newsletter.routes import router as newsletter_route

app = FastAPI()

Base.metadata.create_all(bind=engine)
app.include_router(newsletter_route)

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

if __name__ == "__main__":
    uvicorn.run(
        "main:app",
        host="0.0.0.0",
        port=8000,
        reload=True,
        reload_dirs=[os.path.dirname(os.path.abspath(__file__))],
        reload_excludes=[
            "*/.git/*",
            "*/__pycache__/*",
            "*.pyc",
            "*/.pytest_cache/*",
            "*/.vscode/*",
            "*/.idea/*"
        ],
        reload_delay=1,
        reload_includes=["*.py", "*.html", "*.css", "*.js"]
    )

Este código configura uma aplicação FastAPI para gerenciar newsletters, com middleware, conexões de banco de dados e recarregamento automático. A seguir, um detalhamento de cada componente.

  • Importações: Inclui as bibliotecas necessárias para o funcionamento do FastAPI, como FastAPI para a estrutura principal da API, CORSMiddleware para lidar com o compartilhamento de recursos de origem cruzada (CORS), e módulos personalizados para o banco de dados.
  • Inicialização da Aplicação: Cria uma instância da aplicação FastAPI.
  • Configuração do Banco de Dados: Garante que todas as tabelas do banco de dados sejam criadas usando o ORM do SQLAlchemy.
  • Inclusão de Routers: Registra as rotas relacionadas à newsletter com a aplicação FastAPI.
  • Configuração do Middleware CORS: Permite solicitações de qualquer origem, envio de credenciais (cookies, cabeçalhos de autorização), todos os métodos HTTP e todos os cabeçalhos.
  • Execução da Aplicação: Garante que a aplicação seja executada quando o arquivo é executado diretamente, iniciando o servidor FastAPI com configurações específicas, como host, porta, recarregamento automático e diretórios a serem observados para alterações.

Configurações e Banco de Dados no Projeto FastAPI com SQLAlchemy

O arquivo config.py define as configurações do projeto, utilizando o Pydantic Settings para gerenciar variáveis de ambiente de forma segura e flexível.

from pydantic_settings import BaseSettings

class Settings(BaseSettings):
    DATABASE_URL: str
    class Config:
        env_file = ".env"

settings = Settings()

Este código define uma classe Pydantic Settings para gerenciar variáveis de ambiente, permitindo o carregamento automático de valores de configuração de um arquivo .env ou variáveis de ambiente do sistema. A subclasse Config especifica o arquivo .env como a fonte. Quando uma instância de Settings é criada, ela busca as variáveis de ambiente, permitindo o gerenciamento seguro e flexível da configuração.

O arquivo database.py configura o SQLAlchemy com uma conexão de banco de dados, utilizando a configuração baseada em variáveis de ambiente.

from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from .config import settings

SQLALCHEMY_DATABASE_URL = settings.DATABASE_URL

engine = create_engine(
    SQLALCHEMY_DATABASE_URL,
    connect_args={"check_same_thread": False}
)

SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

Base = declarative_base()

def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()

Este código configura o SQLAlchemy com uma conexão de banco de dados usando configuração baseada em ambiente. Ele importa os componentes necessários do SQLAlchemy, carrega a URL do banco de dados dinamicamente das configurações, cria o engine do banco de dados e gerencia as sessões. Além disso, define uma classe base para os modelos ORM e fornece uma dependência para a sessão do banco de dados.

  • Importar os componentes necessários do SQLAlchemy:
  • Carregar a URL do banco de dados dinamicamente: Ele importa as configurações de config para buscar DATABASE_URL das variáveis de ambiente.
  • Criar o engine do banco de dados: create_engine(SQLALCHEMY_DATABASE_URL, connect_args={“check_same_thread”: False}) inicializa uma conexão. O parâmetro connect_args garante que o SQLite permita que múltiplas threads interajam com o banco de dados.
  • Gerenciamento de Sessão: SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) variável de transações.
  • Classe Base para Modelos ORM: Base = declarative_base() é usado para definir modelos de banco de dados.
  • Dependência para Sessão do Banco de Dados: get_db() fornece uma instância de sessão para operações de banco de dados usando um gerador. Ele garante que a sessão seja devidamente fechada após o uso.

Modelos, Rotas e Schemas para Newsletter

O arquivo models.py define o modelo da tabela de newsletter no banco de dados, utilizando o SQLAlchemy para mapear a classe NewsletterSubscription para a tabela newsletter_subscriptions.

from sqlalchemy import Column, Integer, String, Boolean, DateTime
from database.database import Base
from datetime import datetime

class NewsletterSubscription(Base):
    __tablename__ = "newsletter_subscriptions"
    id = Column(Integer, primary_key=True, index=True)
    email = Column(String(255) , unique=True , nullable=True)
    is_active = Column(Boolean, default=True)
    created_at = Column(DateTime, default=datetime.utcnow)

Este modelo de tabela de Newsletter inclui colunas para id, email, is_active e create_at.

O arquivo routes.py define as rotas da API para gerenciar as inscrições na newsletter. Ele utiliza o FastAPI para criar os endpoints e interage com as funções utilitárias para realizar as operações no banco de dados.

from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.orm import Session
from database.database import get_db
from .schemas import NewsletterSubscriptionBase , NewsletterSubscriptionCreate , NewsletterSubscriptionResponse
from .utils import create_subscription , get_all_subscriptions , delete_subscription

router = APIRouter(prefix="/newsletter", tags=["newsletter"])

@router.post("/subscribe", response_model=NewsletterSubscriptionResponse)
def subscribe(
    subscription: NewsletterSubscriptionCreate,
    db: Session = Depends(get_db)
):
    return create_subscription(db, subscription)

@router.get("/subscriptions", response_model=list[NewsletterSubscriptionResponse])
def get_subscriptions(
    skip: int = 0,
    limit: int = 100,
    db: Session = Depends(get_db)
):
    return get_all_subscriptions(db, skip, limit)

@router.delete("/unsubscribe/{email}")
def unsubscribe(email: str, db: Session = Depends(get_db)):
    if delete_subscription(db, email):
        return {"message": "Successfully unsubscribed"}
    raise HTTPException(
        status_code=status.HTTP_404_NOT_FOUND,
        detail="Subscription not found"
    )

Este arquivo routes.py executa ações usando funções utils, passando parâmetros nas funções. As rotas incluem:

  • subscribe (POST /subscribe): Adiciona uma nova inscrição à rota da newsletter usando a função utils para inscrição.
  • get_subscriptions (GET /subscriptions): Recupera uma lista de todas as inscrições na newsletter com paginação opcional (skip e limit) rota usando a função utils para inscrição.
  • unsubscribe (DELETE /unsubscribe/{email}): Remove uma inscrição usando um email; retorna um erro se o email não for encontrado rota usando a função utils para inscrição.

O arquivo schemas.py define os modelos de dados utilizados para validar e serializar os dados de entrada e saída da API. Ele utiliza o Pydantic para garantir a integridade dos dados e facilitar a comunicação entre a API e o banco de dados.

from pydantic import BaseModel, EmailStr
from datetime import datetime
from typing import Optional

class NewsletterSubscriptionBase(BaseModel):
    email: EmailStr

class NewsletterSubscriptionCreate(NewsletterSubscriptionBase):
    pass

class NewsletterSubscriptionResponse(NewsletterSubscriptionBase):
    id: int
    is_active: bool
    created_at: datetime

    class Config:
        from_attributes = True

Esta configuração garante a validação, serialização e deserialização de dados, tornando-a útil em APIs (por exemplo, FastAPI) para lidar com assinaturas de newsletter de forma eficiente.

  • BaseModel: A classe base para criar modelos Pydantic.
  • EmailStr: Um tipo embutido do Pydantic que valida formatos de email.
  • datetime: Usado para manipular timestamps.
  • Optional: Permite que os campos sejam opcionais.

O modelo base (NewsletterSubscriptionBase) contém um único campo, email, que deve ser um endereço de email válido. Este modelo atua como uma classe base para outros modelos herdarem. O modelo de criação (NewsletterSubscriptionCreate) herda de NewsletterSubscriptionBase e não possui campos adicionais, sendo usado para lidar com a entrada do usuário ao se inscrever.

O modelo de resposta (NewsletterSubscriptionResponse) estende NewsletterSubscriptionBase para incluir campos adicionais: id, is_active e created_at. A classe Config inclui from_attributes = True, permitindo a conversão automática de modelos ORM para modelos Pydantic.

Funções Utilitárias para Gerenciar Inscrições

O arquivo utils.py contém as funções utilitárias para criar, recuperar, listar e deletar as inscrições na newsletter. Ele interage diretamente com o banco de dados, utilizando o SQLAlchemy para realizar as operações.

from sqlalchemy.orm import Session
from . import models, schemas
from fastapi import HTTPException, status

def create_subscription(db: Session, subscription: schemas.NewsletterSubscriptionCreate):
    db_subscription = models.NewsletterSubscription(
        email=subscription.email
    )
    try:
        db.add(db_subscription)
        db.commit()
        db.refresh(db_subscription)
        return db_subscription
    except Exception as e:
        db.rollback()
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Email already subscribed"
        )

def get_subscription(db: Session, email: str):
    return db.query(models.NewsletterSubscription).filter(
        models.NewsletterSubscription.email == email
    ).first()

def get_all_subscriptions(db: Session, skip: int = 0, limit: int = 100):
    return db.query(models.NewsletterSubscription).offset(skip).limit(limit).all()

def delete_subscription(db: Session, email: str):
    subscription = get_subscription(db, email)
    if subscription:
        db.delete(subscription)
        db.commit()
        return True
    return False

Essas funções utilitárias são responsáveis por lidar com a criação de inscrições, recuperação por email, listagem e exclusão. As funções incluem:

  • create_subscription: Adiciona uma nova inscrição de email ao banco de dados. Se o email já estiver inscrito, ele reverte a transação e levanta um erro.
  • get_subscription: Recupera uma inscrição por email.
  • get_all_subscriptions: Busca todas as inscrições com paginação opcional (skip e limit).
  • delete_subscription: Exclui uma inscrição por email se existir; retorna False se não for encontrado.

Primeira: Este conteúdo foi auxiliado por Inteligência Artificiado, mas escrito e revisado por um humano.

Segunda: Via Dev.to

Leave a Comment