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
3 changes: 3 additions & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#esse arquivo env vai subir para o git por ser um projeto de exemplo

SQLALCHEMY_DATABASE_URL = "sqlite:///./movie.db"
73 changes: 49 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,37 +1,62 @@
![WATTIO](http://wattio.com.br/web/image/1204-212f47c3/Logo%20Wattio.png)
# 🎬 API de Filmes

#### Descrição
Uma API REST para cadastro de filmes, desenvolvida com **FastAPI**, utilizando **SQLAlchemy** para persistência de dados em **SQLite**.

O desafio consiste em implementar um CRUD de filmes, utilizando [python](https://www.python.org/ "python") integrando com uma API REST e uma possível persistência de dados.
Este projeto faz parte de um desafio técnico com o objetivo de implementar um CRUD completo de filmes, expondo uma API REST funcional, organizada e de fácil manutenção.

Rotas da API:
---

- `/filmes` - [GET] deve retornar todos os filmes cadastrados.
- `/filmes` - [POST] deve cadastrar um novo filme.
- `/filmes/{id}` - [GET] deve retornar o filme com ID especificado.
## 🚀 Tecnologias utilizadas

O Objetivo é te desafiar e reconhecer seu esforço para aprender e se adaptar. Qualquer código enviado, ficaremos muito felizes e avaliaremos com toda atenção!
- [FastAPI](https://fastapi.tiangolo.com/)
- [SQLAlchemy](https://www.sqlalchemy.org/)
- [SQLite](https://www.sqlite.org/)
- [Pydantic](https://docs.pydantic.dev/)
- [Uvicorn](https://www.uvicorn.org/)
- [Docker](https://www.docker.com/)

#### Sugestão de Ferramentas
Não é obrigatório utilizar todas as as tecnologias sugeridas, mas será um diferencial =]
📚 **Referência complementar**:
[Guia sobre ORMs em Python – Real Python](https://realpython.com/python-sql-libraries/#object-relational-mappers-orms)

- Orientação a objetos (utilizar objetos, classes para manipular os filmes)
- [FastAPI](https://fastapi.tiangolo.com/) (API com documentação auto gerada)
- [Docker](https://www.docker.com/) / [Docker-compose](https://docs.docker.com/compose/install/) (Aplicação deverá ficar em um container docker, e o start deverá seer com o comando ``` docker-compose up ```
- Integração com banco de dados (persistir as informações em json (iniciante) /[SqLite](https://www.sqlite.org/index.html) / [SQLAlchemy](https://fastapi.tiangolo.com/tutorial/sql-databases/#sql-relational-databases) / outros DB)
---

## 🗂️ Funcionalidades

#### Como começar?
- ✅ Criar um novo filme (`POST /filmes/`)
- ✅ Listar todos os filmes cadastrados (`GET /filmes/`)
- ✅ Buscar um filme por ID (`GET /filmes/{id}`)
- ✅ Atualizar um filme (`PUT /filmes/{id}`)
- ✅ Deletar um filme (`DELETE /filmes/{id}`)

- Fork do repositório
- Criar branch com seu nome ``` git checkout -b feature/ana ```
- Faça os commits de suas alterações ``` git commit -m "[ADD] Funcionalidade" ```
- Envie a branch para seu repositório ``` git push origin feature/ana ```
- Navegue até o [Github](https://github.com/), crie seu Pull Request apontando para a branch **```main```**
- Atualize o README.md descrevendo como subir sua aplicação
---

#### Dúvidas?
## 📁 Estrutura de diretórios
movies-api/
├── app/
│ ├── api/ # Arquivos de rota (endpoints)
│ ├── crud/ # Funções de acesso ao banco
│ ├── db/ # Conexão e base do SQLAlchemy
│ ├── models/ # Modelos do banco (ORM)
│ ├── schemas/ # Schemas Pydantic
│ └── main.py # Ponto de entrada da aplicação
├── movies.db # Arquivo SQLite com os dados
├── .env # Variavel de conexão com o banco
├── dockerfile # Containerização
├── docker-compose.yml
└── README.md # Este arquivo
├── requirements.txt # Dependências do projeto

Qualquer dúvida / sugestão / melhoria / orientação adicional só enviar email para [email protected]
---

Salve!
## 🐳 Como rodar com Docker

1. Clone o repositório:

```bash
git clone https://github.com/gMoraes1/API-Filmes.git
cd API-Filmes
Construa e execute a aplicação com Docker Compose:
docker compose up
A aplicação estará disponível em: http://localhost:8000/docs
⚠️ Atenção: O arquivo .env foi incluído neste repositório apenas por ser um desafio técnico.
Nunca suba esse tipo de arquivo em projetos reais, pois ele pode conter informações sensíveis, como senhas e logins.
Binary file added app/__pycache__/main.cpython-310.pyc
Binary file not shown.
Binary file added app/__pycache__/main.cpython-311.pyc
Binary file not shown.
Binary file added app/api/__pycache__/movies.cpython-310.pyc
Binary file not shown.
Binary file added app/api/__pycache__/movies.cpython-311.pyc
Binary file not shown.
36 changes: 36 additions & 0 deletions app/api/movies.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
from fastapi import APIRouter, Depends
from sqlalchemy.orm import Session
from app.db.session import get_db
from app.schemas.movie import *
from app.crud import movies as crud
from fastapi import HTTPException

router = APIRouter()

@router.post("/filmes/", response_model=Movie)
def create_movie(movie: MovieCreate, db: Session = Depends(get_db)):
return crud.create_movie(db, movie)

@router.get("/filmes/", response_model=list[Movie])
def list_movies(skip: int = 0, limit: int = 10, db: Session = Depends(get_db)):
return crud.get_movies(db, skip, limit)

@router.get("/filmes/{movie_id}", response_model=Movie)
def get_movie(movie_id: int, db: Session = Depends(get_db)):
movie = crud.get_movie_by_id(db, movie_id)
if movie:
return movie
else:
raise HTTPException(status_code=404, detail="Movie not found")

@router.delete("/filmes/{movie_id}", response_model=Movie)
def delete_movie(movie_id: int, db: Session = Depends(get_db)):
return crud.delete_movie(db, movie_id)

@router.put("/filmes/{movie_id}", response_model=Movie)
def update_movie(movie_id: int, movie:MovieUpdate, db: Session = Depends(get_db)):
updated = crud.change_movie(db, movie_id, movie)
if updated:
return updated
else:
raise HTTPException(status_code=404, detail="Movie not found")
Binary file added app/crud/__pycache__/movies.cpython-310.pyc
Binary file not shown.
Binary file added app/crud/__pycache__/movies.cpython-311.pyc
Binary file not shown.
49 changes: 49 additions & 0 deletions app/crud/movies.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
from sqlalchemy.orm import Session
from app.models.movie import Movie
from app.schemas.movie import MovieCreate



def create_movie(db: Session, movie: MovieCreate):
db_movie = Movie(
title=movie.title,
director=movie.director,
year=movie.year


)
db.add(db_movie)
db.commit()
db.refresh(db_movie)
return db_movie

def get_movies(db: Session, skip: int = 0, limit: int = 10):
return db.query(Movie).offset(skip).limit(limit).all()



def get_movie_by_id(db: Session, movie_id: int):
return db.query(Movie).filter(Movie.id == movie_id).first()

def delete_movie(db: Session, movie_id: int):
db_movie = db.query(Movie).filter(Movie.id == movie_id).first()
if db_movie:
db.delete(db_movie)
db.commit()
return db_movie
return None


def change_movie(db: Session, movie_id: int, movie_update: MovieCreate):
db_movie = db.query(Movie).filter(Movie.id == movie_id).first()
if db_movie:
if movie_update.title is not None:
db_movie.title = movie_update.title
if movie_update.director is not None:
db_movie.director = movie_update.director
if movie_update.year is not None:
db_movie.year = movie_update.year
db.commit()
db.refresh(db_movie)
return db_movie
return None
Binary file added app/db/__pycache__/base.cpython-310.pyc
Binary file not shown.
Binary file added app/db/__pycache__/base.cpython-311.pyc
Binary file not shown.
Binary file added app/db/__pycache__/session.cpython-310.pyc
Binary file not shown.
Binary file added app/db/__pycache__/session.cpython-311.pyc
Binary file not shown.
3 changes: 3 additions & 0 deletions app/db/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()
18 changes: 18 additions & 0 deletions app/db/session.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from dotenv import load_dotenv
import os
load_dotenv()


engine = create_engine(
os.getenv("SQLALCHEMY_DATABASE_URL"), connect_args={"check_same_thread": False}
)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
10 changes: 10 additions & 0 deletions app/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from fastapi import FastAPI
from app.api import movies
from app.db.base import Base
from app.db.session import engine

app = FastAPI(title="Filmes API")

Base.metadata.create_all(bind=engine)

app.include_router(movies.router)
Binary file added app/models/__pycache__/movie.cpython-310.pyc
Binary file not shown.
Binary file added app/models/__pycache__/movie.cpython-311.pyc
Binary file not shown.
13 changes: 13 additions & 0 deletions app/models/movie.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from sqlalchemy import Column, Integer, String
from app.db.base import Base

class Movie(Base):
__tablename__ = "movies"

id = Column(Integer, primary_key=True, index=True)
title = Column(String, index=True)
director = Column(String)
year = Column(Integer)

class Config:
from_attributes = True
Binary file added app/schemas/__pycache__/movie.cpython-310.pyc
Binary file not shown.
Binary file added app/schemas/__pycache__/movie.cpython-311.pyc
Binary file not shown.
23 changes: 23 additions & 0 deletions app/schemas/movie.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from pydantic import BaseModel

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

class MovieCreate(MovieBase):
pass

class Movie(MovieBase):
id: int

class Config:
from_attributes = True

class MovieUpdate(BaseModel):
title: str | None = None
director: str | None = None
year: int | None = None

class Config:
from_attributes = True
22 changes: 22 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@

services:
api:
build: .
container_name: movies_api
ports:
- "8000:8000"
env_file:
- .env
volumes:
- ./movies.db:/app/movies.db
restart: always

redoc:
image: redocly/redoc
container_name: redocly_doc
ports:
- "8080:80"
environment:
SPEC_URL: "http://localhost:8000/openapi.json"
depends_on:
- api
12 changes: 12 additions & 0 deletions dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

FROM python:3.11-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY ./app ./app
COPY movie.db .

CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
Binary file added movie.db
Binary file not shown.
5 changes: 5 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
fastapi==0.115.3
pydantic==2.11.1
SQLAlchemy==2.0.32
uvicorn==0.30.1
python-dotenv==1.0.0