From a2a3484cde998d1b5058d805f431ff9ccbbbf9d4 Mon Sep 17 00:00:00 2001 From: vinicius Date: Sun, 23 Oct 2022 16:51:28 -0300 Subject: [PATCH 1/8] [ADD] database.py --- database.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 database.py diff --git a/database.py b/database.py new file mode 100644 index 00000000..01986a46 --- /dev/null +++ b/database.py @@ -0,0 +1,22 @@ +from sqlalchemy import create_engine +from sqlalchemy.orm import sessionmaker +from sqlalchemy.ext.declarative import declarative_base + +DATABASE = "sqlite:///db.sqlite3" + +engine = create_engine( + DATABASE, connect_args={"check_same_thread": False}) + + +LocalSession = sessionmaker(autocommit=False, autoflush=False, bind=engine) + +Base = declarative_base() + +def get_db(): + db = LocalSession() + + try: + yield db + + finally: + db.close() \ No newline at end of file From ab8320888297df1e263e3d2fa16974fb5e6ec84a Mon Sep 17 00:00:00 2001 From: vinicius Date: Sun, 23 Oct 2022 16:52:07 -0300 Subject: [PATCH 2/8] [ADD] models.py --- models.py | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 models.py diff --git a/models.py b/models.py new file mode 100644 index 00000000..01240976 --- /dev/null +++ b/models.py @@ -0,0 +1,9 @@ +from sqlalchemy import Column, Integer, String +from database import Base + +class Filme(Base): + + __tablename__ = "Filmes" + + id: int = Column(Integer, primary_key = True, index = True) + titulo: str = Column(String(100), nullable=False) From 11e16ef374146ac0b54bbf02c5efd6beeba17567 Mon Sep 17 00:00:00 2001 From: vinicius Date: Sun, 23 Oct 2022 16:53:11 -0300 Subject: [PATCH 3/8] [ADD] repositories.py --- repositories.py | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 repositories.py diff --git a/repositories.py b/repositories.py new file mode 100644 index 00000000..b1357e70 --- /dev/null +++ b/repositories.py @@ -0,0 +1,29 @@ +from sqlalchemy.orm import Session +from models import Filme + +class FilmeRepository: + @staticmethod + def find_all(db:Session) -> list[Filme]: + return db.query(Filme).all() + + @staticmethod + def save(db: Session, filme:Filme) -> Filme: + db.add(filme) + db.commit() + return filme + + @staticmethod + def find_by_id(db: Session, id: int) -> Filme: + return db.query(Filme).filter(Filme.id == id).first() + + @staticmethod + def exist_by_id(db: Session, id: int): + return db.query(Filme).filter(Filme.id == id).first() is not None + + @staticmethod + def delete_by_id(db: Session, id:int): + filme = db.query(Filme).filter(Filme.id == id).first() + + if filme is not None: + db.delete(filme) + db.commit() From 48657754fb65b62b5ae09a71417194c7b2cdebfd Mon Sep 17 00:00:00 2001 From: vinicius Date: Sun, 23 Oct 2022 16:53:47 -0300 Subject: [PATCH 4/8] [ADD] schemas.py --- schemas.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 schemas.py diff --git a/schemas.py b/schemas.py new file mode 100644 index 00000000..b1c3c3a7 --- /dev/null +++ b/schemas.py @@ -0,0 +1,13 @@ +from pydantic import BaseModel + +class FilmeBase(BaseModel): + titulo: str + +class FilmeRequest(FilmeBase): + ... + +class FilmeResponse(FilmeBase): + id: int + + class Config: + orm_mode = True \ No newline at end of file From 4a6de41ea40c0d2fb0ac2fda4024125cccfa3802 Mon Sep 17 00:00:00 2001 From: vinicius Date: Sun, 23 Oct 2022 16:54:11 -0300 Subject: [PATCH 5/8] [ADD] main.py --- main.py | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 main.py diff --git a/main.py b/main.py new file mode 100644 index 00000000..8c71bd40 --- /dev/null +++ b/main.py @@ -0,0 +1,66 @@ +from fastapi import FastAPI, Depends, HTTPException, status, Response +from sqlalchemy.orm import Session +import uvicorn +from models import Filme +from database import engine, Base, get_db +from repositories import FilmeRepository +from schemas import FilmeRequest, FilmeResponse + +Base.metadata.create_all(bind=engine) + +app = FastAPI() + +@app.post("/filmes", response_model=FilmeResponse, status_code=status.HTTP_201_CREATED) +def create(request: FilmeRequest, db: Session = Depends(get_db)): + + filme = FilmeRepository.save(db,Filme(**request.dict())) + + return FilmeResponse.from_orm(filme) + + +@app.get('/filmes',response_model=list[FilmeResponse]) +def fild_all(db: Session= Depends(get_db)): + + filmes = FilmeRepository.find_all(db) + + return [FilmeResponse.from_orm(filme) for filme in filmes] + + +@app.get('/filmes/{id}', response_model=FilmeResponse) +def find_by_id(id:int, db:Session = Depends(get_db)): + + filme = FilmeRepository.find_by_id(db,id) + + if not filme: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, detail="Filme não encontrado" + ) + + return FilmeResponse.from_orm(filme) + + +@app.delete('/filmes/{id}', status_code=status.HTTP_204_NO_CONTENT) +def delete_by_id(id:int, db:Session = Depends(get_db)): + + if not FilmeRepository.exist_by_id(db,id): + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, detail = "Filme não encontrado" + ) + + FilmeRepository.delete_by_id(db,id) + return Response(status_code=status.HTTP_204_NO_CONTENT) + +@app.put('/filmes/{id}', response_model=FilmeResponse) +def update(id:int,request:FilmeRequest, db:Session = Depends(get_db)): + + if not FilmeRepository.exist_by_id(db,id): + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, detail = "Filme não encontrado" + ) + + filme = FilmeRepository.save(db,Filme(id=id, **request.dict())) + + return FilmeResponse.from_orm(filme) + +if __name__ == '__main__': + uvicorn.run("main:app", host="127.0.0.1", port=5000, log_level="info") \ No newline at end of file From 7c700185d720c839f8f5576c2f599b1bae2c3ad1 Mon Sep 17 00:00:00 2001 From: vinicius Date: Sun, 23 Oct 2022 16:54:49 -0300 Subject: [PATCH 6/8] [ADD] Dockerfile and docker-compose --- Dockerfile | 4 ++++ docker-compose.yaml | 6 ++++++ 2 files changed, 10 insertions(+) create mode 100644 Dockerfile create mode 100644 docker-compose.yaml diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..c3aab595 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,4 @@ +# escape=` +FROM python:3.9.7 + +RUN pip install fastapi uvicorn SQLAlchemy \ No newline at end of file diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 00000000..f1e57d2a --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,6 @@ +services: + + crud: + build: . + command: python main.py + network_mode: 'host' \ No newline at end of file From c6a9e3adec2b05c6ca4afe274040034c1304ae54 Mon Sep 17 00:00:00 2001 From: Vinicius Suga <80865200+ViniciusSuga@users.noreply.github.com> Date: Sun, 23 Oct 2022 17:09:25 -0300 Subject: [PATCH 7/8] Update README.md --- README.md | 37 +++---------------------------------- 1 file changed, 3 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 5c3393a9..b6919a2e 100644 --- a/README.md +++ b/README.md @@ -1,37 +1,6 @@ ![WATTIO](http://wattio.com.br/web/image/1204-212f47c3/Logo%20Wattio.png) -#### Descrição +Para iniciar a aplicação, precisamos do comando +```docker-compose up --build``` -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. - -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. - -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! - -#### Sugestão de Ferramentas -Não é obrigatório utilizar todas as as tecnologias sugeridas, mas será um diferencial =] - -- 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) - - -#### Como começar? - -- 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? - -Qualquer dúvida / sugestão / melhoria / orientação adicional só enviar email para hendrix@wattio.com.br - -Salve! +A aplicação estará em local host e port 5000 From 3e7d5650d96f873a9d1673e86c3b32708ba658f7 Mon Sep 17 00:00:00 2001 From: Vinicius Suga <80865200+ViniciusSuga@users.noreply.github.com> Date: Sun, 23 Oct 2022 17:09:37 -0300 Subject: [PATCH 8/8] Update README.md --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index b6919a2e..49d54f44 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,3 @@ -![WATTIO](http://wattio.com.br/web/image/1204-212f47c3/Logo%20Wattio.png) - Para iniciar a aplicação, precisamos do comando ```docker-compose up --build```