Desenvolvimento Web

MVC em Python com Flask: A Mesma Filosofia, uma Nova Sintaxe

29/08/2025

Introdução: O Mesmo Princípio, uma Nova Sintaxe

A implementação canônica do padrão Model-View-Controller (MVC) no ecossistema Java Web, com sua estrutura formalizada por Servlets e JSPs, representa um estudo de caso clássico sobre separação de responsabilidades, como detalhado nesta análise técnica sobre a arquitetura em Java. Agora, proponho uma mudança de cenário para o universo Python, não para meramente apresentar uma nova tecnologia, mas para explorar como uma filosofia arquitetural se manifesta de formas distintas em ecossistemas diferentes.

Em minha visão, a beleza da engenharia de software reside em reconhecer que, embora as ferramentas e a sintaxe mudem, os princípios fundamentais de um bom design, como a separação de responsabilidades, permanecem universais. A abordagem de Python para o MVC, especialmente com frameworks como o Flask, é menos sobre configuração explícita e mais sobre convenções e dinamismo, refletindo a própria natureza da linguagem.

A Abordagem Pythonica: MVC ou MVT?

No ecossistema Python, especialmente com frameworks como Flask e Django, é comum encontrar a variação MVT (Model-View-Template). Na prática, a filosofia é a mesma do MVC, mas a terminologia é ligeiramente diferente e, em minha percepção, mais descritiva da implementação real:

Para manter a consistência, usarei a terminologia MVC, mas com o entendimento de que o “Controller” em Flask é implementado nas funções de “View”.

Dissecação de um Projeto Real: A Arquitetura do CurriculoATSPro

Para materializar esses conceitos, não há nada mais eficaz do que analisar um projeto concreto. A estrutura do meu projeto CurriculoATSPro, desenvolvido em Flask, serve como um exemplo pragmático de como a separação de responsabilidades do MVC é organizada na prática.

A estrutura de diretórios que adotei é a seguinte:


/CurriculoATSPro
|
├── app/
|   ├── static/         # Arquivos estáticos (CSS, JS, Imagens)
|   ├── templates/      # A camada de Visão (View/Template)
|   |   ├── auth/
|   |   ├── core/
|   |   └── ...
|   ├── auth/
|   |   ├── views.py    # O Controller de autenticação
|   |   └── forms.py
|   ├── core/
|   |   ├── views.py    # O Controller principal
|   |   └── ...
|   ├── models.py       # A camada de Modelo (Model)
|   └── __init__.py
|
└── ... (arquivos de configuração)

1. O Model (app/models.py)

Este arquivo é o coração da lógica de negócio. Aqui, utilizando uma biblioteca como o SQLAlchemy (um ORM), definimos as classes que mapeiam para as tabelas do nosso banco de dados.

Exemplo conceitual de app/models.py


from flask_sqlalchemy import SQLAlchemy
from werkzeug.security import generate_password_hash, check_password_hash

db = SQLAlchemy()

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64), index=True, unique=True)
    email = db.Column(db.String(120), index=True, unique=True)
    password_hash = db.Column(db.String(128))

    def set_password(self, password):
        self.password_hash = generate_password_hash(password)

    def check_password(self, password):
        return check_password_hash(self.password_hash, password)

class Curriculum(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    content = db.Column(db.Text)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'))

Note que o models.py é agnóstico à web. Ele lida puramente com dados e regras de negócio (como a lógica de hashing de senhas), cumprindo perfeitamente seu papel no MVC.

2. A View (app/templates/)

Este diretório contém todos os arquivos HTML que serão renderizados para o usuário. A utilização do motor de templates Jinja2 permite que injetemos dados dinâmicos de forma segura e limpa, sem misturar lógica de programação complexa com a marcação.

Exemplo de app/templates/core/index.html:


{% extends "base.html" %}

{% block content %}
    <div class="container">
        <h1>Bem-vindo ao CurriculoATSPro, {{ current_user.username }}!</h1>
        <p>Aqui você pode gerenciar seus currículos e otimizá-los.</p>
    </div>
{% endblock %}

A View é passiva. Ela apenas exibe os dados que o Controller lhe fornece, como o current_user.username.

3. O Controller (app/auth/views.py e app/core/views.py)

Em Flask, o roteamento e a lógica de controle são elegantemente definidos usando decoradores. Cada função decorada com @blueprint.route(...) é um endpoint que responde a uma requisição HTTP.

Exemplo de app/auth/views.py:


from flask import render_template, flash, redirect, url_for, request
from app.models import User
from . import auth_bp  # 'auth_bp' é o Blueprint
from .forms import LoginForm

@auth_bp.route('/login', methods=['GET', 'POST'])
def login():
    form = LoginForm()
    if form.validate_on_submit():
        # 1. Controller recebe dados do formulário
        user = User.query.filter_by(username=form.username.data).first()

        # 2. Controller interage com o Model
        if user is None or not user.check_password(form.password.data):
            flash('Usuário ou senha inválidos')
            return redirect(url_for('auth.login'))

        # Lógica de login do usuário...

        # 3. Controller seleciona e renderiza a View
        return redirect(url_for('core.index'))

    return render_template('auth/login.html', title='Entrar', form=form)

Observe o fluxo: a função login (Controller) recebe a requisição, interage com o User (Model) para validar as credenciais e, dependendo do resultado, renderiza o template login.html (View) ou redireciona para outra rota.

Conclusão: A Mesma Filosofia, uma Expressão Diferente

Ao contrastar esta implementação com a abordagem Java/Servlet, a diferença de filosofia se torna evidente. Onde Java exige configuração explícita em XML (web.xml), Python utiliza convenções e decoradores para alcançar o mesmo resultado de forma mais concisa.

Contudo, em minha visão, a conclusão é a mesma: a disciplina imposta pelo padrão arquitetural MVC é o que permite que um projeto como o CurriculoATSPro seja organizado em módulos lógicos (auth, core), facilitando o desenvolvimento, a manutenção e a testabilidade. A tecnologia é o meio, mas a arquitetura é a estratégia. E é a estratégia que, no fim, dita o sucesso e a longevidade de um sistema de software.


Referências e Leituras de Apoio

Voltar