Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 0 additions & 37 deletions README.md

This file was deleted.

80 changes: 80 additions & 0 deletions fastapi-filmes/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/

# Jupyter Notebook
.ipynb_checkpoints

# Environments
.env
.venv/
env/
venv/
ENV/
env.bak/
venv.bak/

# VSCode settings
.vscode/

# Docker
*.log
docker-compose.override.yml
docker-compose.override.yaml

# SQLite database file
*.db
*.sqlite3

# Prisma client (se estiver usando)
node_modules/
prisma/client/

# Logs
logs/
*.log

# MacOS
.DS_Store

# Windows
Thumbs.db
20 changes: 20 additions & 0 deletions fastapi-filmes/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Use imagem oficial do Python 3.11 (ou outra versão compatível)
FROM python:3.11-slim

# Defina diretório de trabalho no container
WORKDIR /app

# Copie arquivos de dependências
COPY requirements.txt .

# Instale dependências
RUN pip install --no-cache-dir -r requirements.txt

# Copie o restante do código
COPY . .

# Exponha a porta que a FastAPI vai rodar
EXPOSE 8000

# Comando para rodar a aplicação
CMD ["uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "8000"]
109 changes: 109 additions & 0 deletions fastapi-filmes/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
# 🎬 FastAPI Filmes
API de gerenciamento de filmes desenvolvida em Python utilizando FastAPI, SQLAlchemy e SQLite.
O projeto foi estruturado seguindo boas práticas de orientação a objetos e inclui testes automatizados com pytest, além de suporte a Docker e docker-compose.

---

## 🚀 Tecnologias Utilizadas
- FastAPI – Framework para APIs rápidas

- SQLAlchemy – ORM para persistência de dados

- SQLite – Banco de dados leve

- Pydantic – Validação de dados

- Docker – Containerização

- Pytest – Testes automatizados

---

## 📂 Estrutura do Projeto
```bash
fastapi-filmes/
│── src/
│ ├── api/ # Rotas da aplicação
│ ├── core/ # Configurações
│ ├── db/ # Banco de dados
│ ├── schemas/ # Schemas Pydantic
│ ├── models/ # Tabelas do banco
│ ├── services/ # Regras de negócio
│ └── main.py # Ponto de entrada da API
│── tests/ # Testes automatizados
│── Dockerfile
│── docker-compose.yml
│── requirements.txt
│── README.md
└── .gitignore
```

## ⚙️ Configuração do Ambiente
### 1️⃣ Clonar o repositório
```bash
git clone https://github.com/seu-usuario/fastapi-filmes.git
cd fastapi-filmes
```

### 2️⃣ Criar ambiente virtual (opcional)
```bash
python -m venv venv
source venv/bin/activate # Linux/Mac
venv\Scripts\activate # Windows
```

### 3️⃣ Instalar dependências
```bash
pip install -r requirements.txt
```

---

### ▶️ Executando a API Localmente
```bash
uvicorn src.main:app --reload
```
Acesse:

- Swagger: http://localhost:8000/docs

- ReDoc: http://localhost:8000/redoc

## 🐳 Executando com Docker
### 1️⃣ Build da imagem
```bash
docker-compose up --build
```

A API estará disponível em http://localhost:8000

## 🧪 Rodando Testes
Para rodar os testes unitários:

```bash
pytest tests/ --asyncio-mode=auto -v
```

##📌 Endpoints Disponíveis
- GET /filmes

Retorna a lista de filmes.

- POST /filmes

Cria um novo filme.

Exemplo:

```json
{
"title": "Matrix",
"director": "Wachowski",
"year": 1999
}
```

- GET /filmes/{id}

Retorna um filme específico pelo ID.
12 changes: 12 additions & 0 deletions fastapi-filmes/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
version: "3.8"

services:
api:
build: .
ports:
- "8000:8000"
volumes:
- ./:/app
environment:
- PYTHONUNBUFFERED=1
command: uvicorn src.main:app --host 0.0.0.0 --port 8000 --reload
7 changes: 7 additions & 0 deletions fastapi-filmes/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
fastapi
uvicorn
sqlalchemy
pydantic
pytest
pytest-asyncio
httpx
1 change: 1 addition & 0 deletions fastapi-filmes/src/api/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .router import router
Binary file not shown.
Binary file not shown.
31 changes: 31 additions & 0 deletions fastapi-filmes/src/api/router.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from fastapi import APIRouter, Depends
from typing import List
from src.db.database import SessionLocal
from sqlalchemy.orm import Session
from src.schemas import Film, FilmCreate
from src.services import FilmService

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


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

@router.get("/", response_model=List[Film])
async def get_films(db: Session = Depends(get_db)):
film_service = FilmService(db)
return film_service.get_all_films()

@router.post("/", response_model=Film)
async def create_film(film: FilmCreate,db: Session = Depends(get_db)):
film_service = FilmService(db)
return film_service.create_film(film)

@router.get("/{id}")
def get_film(id: int, db: Session = Depends(get_db)):
service = FilmService(db)
return service.get_film(id)
Empty file.
Binary file not shown.
Binary file not shown.
7 changes: 7 additions & 0 deletions fastapi-filmes/src/core/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import os

class Settings:
PROJECT_NAME: str = "FastAPI Filmes"
DATABASE_URL: str = os.getenv("DATABASE_URL", "sqlite:///./films.db")

settings = Settings()
1 change: 1 addition & 0 deletions fastapi-filmes/src/db/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .database import Base, engine, SessionLocal
Binary file not shown.
Binary file not shown.
8 changes: 8 additions & 0 deletions fastapi-filmes/src/db/database.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from src.core.config import settings

engine = create_engine(settings.DATABASE_URL, connect_args={"check_same_thread": False})
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()
13 changes: 13 additions & 0 deletions fastapi-filmes/src/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from fastapi import FastAPI
from src.api import router
from src.db import Base, engine

app = FastAPI(title="API Filmes")

Base.metadata.create_all(bind=engine)

app.include_router(router)

@app.get("/")
async def root():
return {"message": "API Filmes rodando!"}
10 changes: 10 additions & 0 deletions fastapi-filmes/src/models/film.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from sqlalchemy import Column, Integer, String
from src.db.database import Base

class FilmModel(Base):
__tablename__ = "films"

id = Column(Integer, primary_key=True, index=True)
title = Column(String, index=True)
director = Column(String, index=True)
year = Column(Integer)
1 change: 1 addition & 0 deletions fastapi-filmes/src/schemas/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .film import Film, FilmCreate
Binary file not shown.
Binary file not shown.
15 changes: 15 additions & 0 deletions fastapi-filmes/src/schemas/film.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from pydantic import BaseModel

class FilmBase(BaseModel):
title: str
director: str
year: int

class FilmCreate(FilmBase):
pass

class Film(FilmBase):
id: int

class Config:
orm_mode = True
1 change: 1 addition & 0 deletions fastapi-filmes/src/services/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .film_service import FilmService
Binary file not shown.
Binary file not shown.
20 changes: 20 additions & 0 deletions fastapi-filmes/src/services/film_service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from sqlalchemy.orm import Session
from src.schemas import FilmCreate
from src.models.film import FilmModel

class FilmService:
def __init__(self, db: Session):
self.db = db

def get_all_films(self):
return self.db.query(FilmModel).all()

def create_film(self, film_create: FilmCreate):
film = FilmModel(**film_create.dict())
self.db.add(film)
self.db.commit()
self.db.refresh(film)
return film

def get_film(self, id: int):
return self.db.query(FilmModel).filter(FilmModel.id == id).first()
Empty file.
Binary file not shown.
Binary file not shown.
Loading