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