diff --git a/Docker-compose.yml b/Docker-compose.yml new file mode 100644 index 000000000..1fb09fc9a --- /dev/null +++ b/Docker-compose.yml @@ -0,0 +1,10 @@ +services: + app: + build: + context: . + dockerfile: Dockerfile + ports: + - "8000:8000" + volumes: + - ./app:/app + command: uvicorn app.main:app --host 0.0.0.0 --port 8000 \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..6892693aa --- /dev/null +++ b/Dockerfile @@ -0,0 +1,9 @@ +FROM python:3.10-slim + +COPY requirements.txt requirements + +RUN pip install --no-cache-dir -r requirements + +COPY . . + +CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8080"] \ No newline at end of file diff --git a/README.md b/README.md index 5c3393a97..1d8a2dbe6 100644 --- a/README.md +++ b/README.md @@ -1,37 +1,113 @@ -![WATTIO](http://wattio.com.br/web/image/1204-212f47c3/Logo%20Wattio.png) +# Filmes API -#### Descrição +Esta é uma API desenvolvida em Python com o framework FastAPI, projetada para gerenciar informações sobre filmes. A aplicação utiliza um banco de dados SQLite para armazenar os dados e pode ser executada em um ambiente Docker. -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. +## Recursos da API -Rotas da API: +A API suporta as seguintes operações: - - `/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. +- **Listar todos os filmes**: `GET /Filmes` +- **Obter detalhes de um filme pelo ID**: `GET /Filmes/{id}` +- **Adicionar um novo filme**: `POST /Filmes` -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! +## Requisitos -#### Sugestão de Ferramentas -Não é obrigatório utilizar todas as as tecnologias sugeridas, mas será um diferencial =] +Certifique-se de ter instalado os seguintes componentes: -- 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) +- [Python 3.9+](https://www.python.org/) +- [Docker](https://www.docker.com/) +- [Git](https://git-scm.com/) +## Instalação e Execução do Projeto -#### Como começar? +1. Clone este repositório: -- 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 +```bash +git clone +cd WATTIO-TESTE +``` -#### Dúvidas? +2. Construa e inicie os containers Docker: -Qualquer dúvida / sugestão / melhoria / orientação adicional só enviar email para hendrix@wattio.com.br +```bash +docker-compose up --build +``` + +3. Acesse a documentação interativa da API no navegador: + +``` +http://localhost:8000/docs +``` + +4. As rotas da API estão detalhadas abaixo: + +### Listar todos os filmes + +**Requisição:** + +```bash +GET /Filmes +``` + +**Resposta:** + +```json +[ + { + "id": 1, + "titulo": "Scarface", + "diretor": "Brian de Palma" + }, + { + "id": 2, + "titulo": "Bastardos Inglórios", + "diretor": "Quentin Tarantino" + } +] +``` + +### Obter detalhes de um filme pelo ID + +**Requisição:** + +```bash +GET /Filmes/{id} +``` + +**Resposta:** + +```json +{ + "id": 1, + "titulo": "Scarface", + "diretor": "Brian de Palma" +} +``` + +### Adicionar um novo filme + +**Requisição:** + +```bash +POST /Filmes +``` + +**Corpo da Requisição:** + +```json +{ + "titulo": "Matrix", + "diretor": "Lana Wachowski e Lilly Wachowski" +} +``` + +**Resposta:** + +```json +{ + "id": 4, + "titulo": "Matrix", + "diretor": "Lana Wachowski e Lilly Wachowski" +} +``` -Salve! diff --git a/app/__init__.py b/app/__init__.py new file mode 100644 index 000000000..095cb542f --- /dev/null +++ b/app/__init__.py @@ -0,0 +1 @@ +from .import main \ No newline at end of file diff --git a/app/__pycache__/__init__.cpython-310.pyc b/app/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 000000000..c42f0682b Binary files /dev/null and b/app/__pycache__/__init__.cpython-310.pyc differ diff --git a/app/__pycache__/main.cpython-310.pyc b/app/__pycache__/main.cpython-310.pyc new file mode 100644 index 000000000..cc22f14f2 Binary files /dev/null and b/app/__pycache__/main.cpython-310.pyc differ diff --git a/app/main.py b/app/main.py new file mode 100644 index 000000000..a1e657386 --- /dev/null +++ b/app/main.py @@ -0,0 +1,62 @@ +from fastapi import FastAPI, HTTPException, Depends, status +from typing import Dict, Any +from sqlalchemy import Integer, String, Column, create_engine +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.orm import sessionmaker, Session + +app = FastAPI() + +url_db = "sqlite:///./filmes_db" +engine = create_engine(url_db,connect_args={"check_same_thread":False}) +session_id = sessionmaker(autocommit=False, autoflush=False, bind = engine) +Base = declarative_base() + +class Filme(Base): + __tablename__ = "filmes" + + id = Column(Integer, primary_key=True, index=True) + titulo = Column(String, index=True) + diretor = Column(String) + +Base.metadata.create_all(bind=engine) + +def get_session(): + db_connect = session_id() + try: + yield db_connect + finally: + db_connect.close() + +def initial_db(): + with session_id() as session_db: + if not session_db.query(Filme).first(): + filmes_add = [ + Filme(titulo="Scarface", diretor="Brian de Palma"), + Filme(titulo="Bastardos Inglórios", diretor = "Quentin Tarantino"), + Filme(titulo="Interestelar", diretor="Christopher Nolan") + ] + session_db.add_all(filmes_add) + session_db.commit() + +initial_db() + + +@app.get("/Filmes") +def todos_filmes(db: Session=Depends(get_session)): + todos_filme = db.query(Filme).all() + return todos_filme + +@app.get("/Filmes/{id}") +def filmes_id(id:int, db: Session = Depends(get_session)): + filme_unico = db.query(Filme).filter(Filme.id==id).first() + if not filme_unico: + raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Filme não encontrado") + return filme_unico + +@app.post("/Filmes") +def criar_filme(titulo:str, diretor:str, db: Session=Depends(get_session)): + novo_filme = Filme(titulo=titulo, diretor=diretor) + db.add(novo_filme) + db.commit() + db.refresh(novo_filme) + return novo_filme diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 000000000..e0266e7d4 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +fastapi +uvicorn +sqlalchemy \ No newline at end of file