Commit inicial: estrutura o projeto MVC

This commit is contained in:
Fernanda
2026-04-07 18:07:06 -03:00
parent 36777c4537
commit 4e21f32e6f
16 changed files with 286 additions and 63 deletions
+11 -62
View File
@@ -1,68 +1,17 @@
from flask import Flask, request, jsonify from flask import Flask
from database import db
from controller.usuario_controller import usuario_bp
from controller.dispositivo_controller import dispositivo_bp
# Define os parametros utilizadas na API
app = Flask(__name__) app = Flask(__name__)
tasks = [] # Lista para armazenar as tarefas app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///graphics_analytics.db'
task_id_control = 1 # Controlador de IDs para garantir unicidade
# Algoritimo para uma rota basica '/' para teste db.init_app(app)
@app.route("/", methods=["GET"]) app.register_blueprint(usuario_bp)
def hello(): app.register_blueprint(dispositivo_bp)
return "Hello, World!"
# Algoritimo para rota '/tasks' sendo um algoritimo simples de gravação de cabeçalho para depois ser consultado por metodo GET with app.app_context():
@app.route("/tasks", methods=["POST"]) db.create_all()
def create_task():
global task_id_control
data = request.get_json() # Pega os dados enviados no corpo da requisição
new_task = {
"id": task_id_control,
"title": data.get("title"), # Obtém o título enviado
"description": data.get("description", ""), # Descrição opcional
"completed": False # Define que a tarefa começa como incompleta
}
tasks.append(new_task) # Adiciona a nova tarefa à lista
task_id_control += 1 # Incrementa o ID para a próxima tarefa
return jsonify({"message": "Tarefa criada com sucesso!", "task": new_task}), 201
# Algoritmo simples para consulta simples para consulta de total de "tasks" gravadas na API if __name__ == '__main__':
@app.route("/tasks", methods=["GET"])
def get_tasks():
return jsonify({"tasks": tasks, "total": len(tasks)})
# Algoritimo simples para consulta do dado gravado dado um "ID" de valor inteiro para consulta
@app.route("/tasks/<int:task_id>", methods=["GET"])
def get_task(task_id):
# Procura a tarefa pelo ID
task = next((t for t in tasks if t["id"] == task_id), None)
if not task:
return jsonify({"message": "Tarefa não encontrada"}), 404
return jsonify(task)
# Algoritimo simples para atualizar dados de uma tarefa já gravada utilizando o "ID" da tarefa a ser editada
@app.route("/tasks/<int:task_id>", methods=["PUT"])
def update_task(task_id):
task = next((t for t in tasks if t["id"] == task_id), None)
if not task:
return jsonify({"message": "Tarefa não encontrada"}), 404
data = request.get_json()
# Atualiza os campos da tarefa com os dados enviados
task["title"] = data.get("title", task["title"])
task["description"] = data.get("description", task["description"])
task["completed"] = data.get("completed", task["completed"])
return jsonify({"message": "Tarefa atualizada com sucesso!", "task": task})
# Algoritimo simples para deletar uma tarefa pela "ID"
@app.route("/tasks/<int:task_id>", methods=["DELETE"])
def delete_task(task_id):
global tasks
task = next((t for t in tasks if t["id"] == task_id), None)
if not task:
return jsonify({"message": "Tarefa não encontrada"}), 404
tasks = [t for t in tasks if t["id"] != task_id]
return jsonify({"message": "Tarefa deletada com sucesso!"})
# Essa parte do código deverá estar no final do projeto para realizar o algoritimo acima
if __name__ == "__main__":
app.run(debug=True) app.run(debug=True)
+44
View File
@@ -0,0 +1,44 @@
from flask import Blueprint, request, jsonify
from service.dispositivo_service import DispositivoService
from model.dispositivo import DispositivoNaoEncontrado
dispositivo_bp = Blueprint('dispositivo', __name__)
@dispositivo_bp.route('/dispositivos', methods=['POST'])
def criar():
dados = request.get_json()
dispositivo = DispositivoService.instancia().criar(
usuario_id=dados['usuario_id'],
nome=dados['nome'],
descricao=dados.get('descricao')
)
return jsonify({
"id": dispositivo.id,
"usuario_id": dispositivo.usuario_id,
"nome": dispositivo.nome,
"descricao": dispositivo.descricao,
"chave": dispositivo.chave,
"ativo": dispositivo.ativo
}), 201
@dispositivo_bp.route('/dispositivos/<int:usuario_id>', methods=['GET'])
def listar(usuario_id):
dispositivos = DispositivoService.instancia().listar_por_usuario(usuario_id)
return jsonify([{
"id": d.id,
"nome": d.nome,
"descricao": d.descricao,
"chave": d.chave,
"ativo": d.ativo
} for d in dispositivos])
@dispositivo_bp.route('/dispositivos/<int:id>', methods=['DELETE'])
def deletar(id):
try:
DispositivoService.instancia().deletar(id)
return jsonify({"mensagem": "Dispositivo deletado"}), 200
except DispositivoNaoEncontrado:
return jsonify({"erro": "Dispositivo nao encontrado"}), 404
+38
View File
@@ -0,0 +1,38 @@
from flask import Blueprint, request, jsonify
from service.usuario_service import UsuarioService
from model.usuario import EmailJaCadastrado, UsuarioNaoEncontrado
usuario_bp = Blueprint('usuario', __name__)
@usuario_bp.route('/auth/registro', methods=['POST'])
def registrar():
dados = request.get_json()
try:
usuario = UsuarioService.instancia().registrar(
nome=dados['nome'],
email=dados['email'],
senha=dados['senha']
)
return jsonify({
"id": usuario.id,
"nome": usuario.nome,
"email": usuario.email,
"token_api": usuario.token_api
}), 201
except EmailJaCadastrado:
return jsonify({"erro": "Email ja cadastrado"}), 409
@usuario_bp.route('/auth/usuario/<int:id>', methods=['GET'])
def buscar(id):
try:
usuario = UsuarioService.instancia().buscar_por_id(id)
return jsonify({
"id": usuario.id,
"nome": usuario.nome,
"email": usuario.email,
"token_api": usuario.token_api
})
except UsuarioNaoEncontrado:
return jsonify({"erro": "Usuario nao encontrado"}), 404
View File
+30
View File
@@ -0,0 +1,30 @@
from model.dispositivo import Dispositivo
from database import db
class DispositivoDao:
_instancia = None
@classmethod
def instancia(cls):
if cls._instancia is None:
cls._instancia = cls()
return cls._instancia
def criar(self, dispositivo):
db.session.add(dispositivo)
db.session.commit()
return dispositivo
def buscar_por_id(self, id):
return db.session.get(Dispositivo, id)
def buscar_por_chave(self, chave):
return Dispositivo.query.filter_by(chave=chave).first()
def listar_por_usuario(self, usuario_id):
return Dispositivo.query.filter_by(usuario_id=usuario_id).all()
def deletar(self, dispositivo):
db.session.delete(dispositivo)
db.session.commit()
+26
View File
@@ -0,0 +1,26 @@
from model.usuario import Usuario
from database import db
class UsuarioDao:
_instancia = None
@classmethod
def instancia(cls):
if cls._instancia is None:
cls._instancia = cls()
return cls._instancia
def criar(self, usuario):
db.session.add(usuario)
db.session.commit()
return usuario
def buscar_por_id(self, id):
return db.session.get(Usuario, id)
def buscar_por_email(self, email):
return Usuario.query.filter_by(email=email).first()
def buscar_por_token(self, token_api):
return Usuario.query.filter_by(token_api=token_api).first()
+3
View File
@@ -0,0 +1,3 @@
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
View File
+19
View File
@@ -0,0 +1,19 @@
from database import db
from datetime import datetime
import uuid
class DispositivoNaoEncontrado(Exception):
pass
class Dispositivo(db.Model):
__tablename__ = 'dispositivos'
id = db.Column(db.Integer, primary_key=True)
usuario_id = db.Column(db.Integer, db.ForeignKey('usuarios.id'), nullable=False)
nome = db.Column(db.String(100), nullable=False)
descricao = db.Column(db.String(200))
chave = db.Column(db.String(36), unique=True, default=lambda: str(uuid.uuid4()), nullable=False)
ativo = db.Column(db.Boolean, default=True)
criado_em = db.Column(db.DateTime, default=datetime.utcnow)
+15
View File
@@ -0,0 +1,15 @@
from database import db
from datetime import datetime
class LeituraNaoEncontrada(Exception):
pass
class Leitura(db.Model):
__tablename__ = 'leituras'
id = db.Column(db.Integer, primary_key=True)
dispositivo_id = db.Column(db.Integer, db.ForeignKey('dispositivos.id'), nullable=False)
payload = db.Column(db.JSON, nullable=False)
criado_em = db.Column(db.DateTime, default=datetime.utcnow)
+21
View File
@@ -0,0 +1,21 @@
from database import db
from datetime import datetime
import uuid
class UsuarioNaoEncontrado(Exception):
pass
class EmailJaCadastrado(Exception):
pass
class Usuario(db.Model):
__tablename__ = 'usuarios'
id = db.Column(db.Integer, primary_key=True)
nome = db.Column(db.String(100), nullable=False)
email = db.Column(db.String(150), unique=True, nullable=False)
senha_hash = db.Column(db.String(255), nullable=False)
token_api = db.Column(db.String(36), unique=True, default=lambda: str(uuid.uuid4()))
criado_em = db.Column(db.DateTime, default=datetime.utcnow)
+4
View File
@@ -0,0 +1,4 @@
flask
flask-sqlalchemy
psycopg2-binary
bcrypt
View File
+40
View File
@@ -0,0 +1,40 @@
from model.dispositivo import Dispositivo, DispositivoNaoEncontrado
from dao.dispositivo_dao import DispositivoDao
class DispositivoService:
_instancia = None
@classmethod
def instancia(cls):
if cls._instancia is None:
cls._instancia = cls()
return cls._instancia
def __init__(self):
self.dao = DispositivoDao.instancia()
def criar(self, usuario_id, nome, descricao=None):
dispositivo = Dispositivo(usuario_id=usuario_id, nome=nome, descricao=descricao)
return self.dao.criar(dispositivo)
def buscar_por_id(self, id):
dispositivo = self.dao.buscar_por_id(id)
if not dispositivo:
raise DispositivoNaoEncontrado()
return dispositivo
def buscar_por_chave(self, chave):
dispositivo = self.dao.buscar_por_chave(chave)
if not dispositivo:
raise DispositivoNaoEncontrado()
return dispositivo
def listar_por_usuario(self, usuario_id):
return self.dao.listar_por_usuario(usuario_id)
def deletar(self, id):
dispositivo = self.dao.buscar_por_id(id)
if not dispositivo:
raise DispositivoNaoEncontrado()
self.dao.deletar(dispositivo)
+34
View File
@@ -0,0 +1,34 @@
from model.usuario import Usuario, UsuarioNaoEncontrado, EmailJaCadastrado
from dao.usuario_dao import UsuarioDao
import bcrypt
class UsuarioService:
_instancia = None
@classmethod
def instancia(cls):
if cls._instancia is None:
cls._instancia = cls()
return cls._instancia
def __init__(self):
self.dao = UsuarioDao.instancia()
def registrar(self, nome, email, senha):
if self.dao.buscar_por_email(email):
raise EmailJaCadastrado()
senha_hash = bcrypt.hashpw(
senha.encode('utf-8'),
bcrypt.gensalt()
).decode('utf-8')
usuario = Usuario(nome=nome, email=email, senha_hash=senha_hash)
return self.dao.criar(usuario)
def buscar_por_id(self, id):
usuario = self.dao.buscar_por_id(id)
if not usuario:
raise UsuarioNaoEncontrado()
return usuario