3
respostas

[Sugestão] Incrementação do projeto

Gostei bastante desse curso e gostaria de incrementar esse API para cadastrar novos usuários a partir da tela de login. Quero uma luz de como posso fazer isso.

3 respostas

Olá Flávio.
Essa vontade de sempre querer mais é que nos torna profissionais mais preparados para enfrentar as demandas que o mercado exige.
Vamos tentar te ajudar a achar o caminho.
Abaixo te explico passo a passo como estruturar isso, com exemplos de código e dicas de segurança.
Estrutura do Projeto

flask_app/
├── app.py
├── config.py
├── models.py
├── forms.py
├── routes.py
├── static/
│   └── uploads/
├── templates/
│   ├── base.html
│   ├── login.html
│   ├── register.html
│   ├── dashboard.html
│   └── crud.html
└── venv/
  1. Configuração básica (config.py)
import os

class Config:
    SECRET_KEY = os.environ.get('SECRET_KEY') or 'chave-secreta-supersegura'
    SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://usuario:senha@localhost/nome_do_banco'
    SQLALCHEMY_TRACK_MODIFICATIONS = False
    UPLOAD_FOLDER = os.path.join(os.getcwd(), 'static/uploads')
    MAX_CONTENT_LENGTH = 2 * 1024 * 1024  # 2MB
  1. Modelos com SQLAlchemy (models.py)
from flask_sqlalchemy import SQLAlchemy
from flask_bcrypt import Bcrypt
from datetime import datetime

db = SQLAlchemy()
bcrypt = Bcrypt()

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True, nullable=False)
    email = db.Column(db.String(120), unique=True, nullable=False)
    password_hash = db.Column(db.String(128), nullable=False)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)

    def set_password(self, password):
        self.password_hash = bcrypt.generate_password_hash(password).decode('utf-8')

    def check_password(self, password):
        return bcrypt.check_password_hash(self.password_hash, password)
  1. Formulários com Flask-WTF (forms.py)
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField, FileField
from wtforms.validators import DataRequired, Email, EqualTo, Length

class LoginForm(FlaskForm):
    email = StringField('Email', validators=[DataRequired(), Email()])
    password = PasswordField('Senha', validators=[DataRequired()])
    submit = SubmitField('Entrar')

class RegisterForm(FlaskForm):
    username = StringField('Usuário', validators=[DataRequired(), Length(min=3, max=50)])
    email = StringField('Email', validators=[DataRequired(), Email()])
    password = PasswordField('Senha', validators=[DataRequired(), Length(min=6)])
    confirm_password = PasswordField('Confirmar Senha', validators=[DataRequired(), EqualTo('password')])
    submit = SubmitField('Cadastrar')

class UploadForm(FlaskForm):
    file = FileField('Selecionar arquivo', validators=[DataRequired()])
    submit = SubmitField('Upload')

continua...

...

  1. Rotas e CRUD (routes.py)
import os
from flask import render_template, redirect, url_for, flash, request, session, current_app
from werkzeug.utils import secure_filename
from models import db, User
from forms import LoginForm, RegisterForm, UploadForm

def init_routes(app):

    @app.route('/')
    def index():
        return render_template('login.html')

    # --- LOGIN ---
    @app.route('/login', methods=['GET', 'POST'])
    def login():
        form = LoginForm()
        if form.validate_on_submit():
            user = User.query.filter_by(email=form.email.data).first()
            if user and user.check_password(form.password.data):
                session['user_id'] = user.id
                flash('Login realizado com sucesso!', 'success')
                return redirect(url_for('dashboard'))
            flash('Email ou senha inválidos', 'danger')
        return render_template('login.html', form=form)

    # --- REGISTRO DE NOVO USUÁRIO ---
    @app.route('/register', methods=['GET', 'POST'])
    def register():
        form = RegisterForm()
        if form.validate_on_submit():
            user = User(username=form.username.data, email=form.email.data)
            user.set_password(form.password.data)
            db.session.add(user)
            db.session.commit()
            flash('Cadastro realizado com sucesso! Faça login.', 'success')
            return redirect(url_for('login'))
        return render_template('register.html', form=form)

    # --- DASHBOARD ---
    @app.route('/dashboard')
    def dashboard():
        if 'user_id' not in session:
            return redirect(url_for('login'))
        return render_template('dashboard.html')

    # --- UPLOAD DE ARQUIVO ---
    @app.route('/upload', methods=['GET', 'POST'])
    def upload_file():
        form = UploadForm()
        if form.validate_on_submit():
            file = form.file.data
            filename = secure_filename(file.filename)
            file.save(os.path.join(current_app.config['UPLOAD_FOLDER'], filename))
            flash('Arquivo enviado com sucesso!', 'success')
            return redirect(url_for('dashboard'))
        return render_template('upload.html', form=form)

    # --- LOGOUT ---
    @app.route('/logout')
    def logout():
        session.pop('user_id', None)
        flash('Você saiu da conta.', 'info')
        return redirect(url_for('login'))
  1. Inicialização do app (app.py)
from flask import Flask
from config import Config
from models import db, bcrypt
from routes import init_routes

app = Flask(__name__)
app.config.from_object(Config)

db.init_app(app)
bcrypt.init_app(app)

with app.app_context():
    db.create_all()

init_routes(app)

if __name__ == '__main__':
    app.run(debug=True)

Dicas de Segurança

  1. Nunca salve senhas em texto puro.
    Use Flask-Bcrypt (como no exemplo).
  2. Proteja uploads:
    • Verifique tipo de arquivo (ex: imagens apenas).
    • Use nomes únicos para evitar sobrescritas.
  3. Use variáveis de ambiente:
    Guarde SECRET_KEY e credenciais do MySQL em .env.
  4. Use flask-login para gerenciamento de sessão mais seguro (opcional, mas recomendado).

Você pode colocar um link na tela de login:

<p>Não tem conta? <a href="{{ url_for('register') }}">Cadastre-se aqui</a></p>

E isso levará o usuário diretamente para o formulário de registro, como implementado acima.
Vai fazendo ai e aproveita os conhecimentos que adquiriu no curso para complementar ou corrigir.
Se tiver alguma duvida pode perguntar.
Então é mão na massa e vai dando feedback com os resultados e experiencias.
Bons estudos.
Se quiser saber mais comente ai ...
Até...

Opa, muito obrigado pelo suporte. Assim que eu estiver com o pc em maos, tentarei. Obrigado novamente.