Skip to main content

Directory Overview

The project follows a modular architecture organized by domain and responsibility:
muebles-roble-diseno-app/
├── app/                          # Main application package
│   ├── __init__.py               # Flask app factory
│   ├── extensions.py             # Flask extensions (SQLAlchemy, CSRF, Migrate)
│   ├── exceptions.py             # Custom exceptions and error handlers
│   │
│   ├── catalogs/                 # Catalog modules
│   │   ├── colors/               # Color management
│   │   │   ├── __init__.py       # Blueprint registration
│   │   │   ├── routes.py         # Routes and controllers
│   │   │   ├── services.py       # Business logic
│   │   │   └── forms.py          # WTForms forms
│   │   ├── wood_types/           # Wood types management
│   │   ├── furniture_type/       # Furniture types
│   │   ├── roles/                # User roles
│   │   └── unit_of_measures/     # Measurement units
│   │
│   ├── models/                   # Database models (ORM)
│   │   ├── __init__.py
│   │   ├── color.py
│   │   ├── wood_type.py
│   │   ├── furniture_type.py
│   │   ├── role.py
│   │   └── unit_of_measure.py
│   │
│   └── templates/                # Jinja2 HTML templates
│       ├── base.html             # Base layout
│       ├── colors/               # Color templates
│       │   ├── list.html
│       │   ├── create.html
│       │   └── edit.html
│       ├── errors/               # Error pages
│       ├── furniture_types/
│       ├── roles/
│       ├── unit_of_measures/
│       └── wood_types/

├── migrations/                   # Database migrations (Alembic)
│   └── versions/

├── docs/                         # Project documentation
│   ├── ARCHITECTURE.md
│   └── CODING_CONVENTIONS.md

├── config.py                     # Application configuration
├── run.py                        # Application entry point
├── requirements.txt              # Python dependencies
├── .env                          # Environment variables (not versioned)
├── .env-template                 # Environment template
└── README.md

Architectural Layers

The application follows a layered MVC architecture with clear separation of concerns:
┌─────────────────────────────────────────────────────────────┐
│                    PRESENTATION LAYER                       │
│               (routes.py + Jinja2 templates)                │
│          Routes / Controllers / HTML Views                  │
├─────────────────────────────────────────────────────────────┤
│                  BUSINESS LOGIC LAYER                       │
│                      (services.py)                          │
│     Business Rules / Validations / Processing               │
├─────────────────────────────────────────────────────────────┤
│                    DATA/MODEL LAYER                         │
│                       (models/)                             │
│          Entities / ORM SQLAlchemy / Database               │
└─────────────────────────────────────────────────────────────┘

Presentation

routes.py + templates/Handles HTTP requests, renders views, manages form submission

Business Logic

services.pyContains domain logic, validations, and orchestrates operations

Data Layer

models/Defines entities and database mappings using SQLAlchemy ORM

Layer Responsibilities

LayerFilesResponsibility
Presentationroutes.py + templates/Define routes, receive HTTP requests, render HTML with Jinja2
Servicesservices.pyBusiness logic, validations, operation orchestration
Modelsmodels/*.pyDefine entities and map to database tables via SQLAlchemy ORM
Configurationconfig.py, extensions.pyEnvironment config, database connection, Flask extensions

Module Organization

Domain Module Structure

Each domain module (e.g., colors, wood_types) follows a consistent structure:
catalogs/
└── colors/
    ├── __init__.py      # Blueprint and exports
    ├── routes.py        # Routes and controllers
    ├── services.py      # Business logic
    └── forms.py         # WTForms forms

Example: Colors Module

1

Blueprint Registration

__init__.py creates and exports the Flask Blueprint:
app/catalogs/colors/__init__.py
from flask import Blueprint

colors_bp = Blueprint('colors', __name__)

from . import routes  # noqa: E402, F401
2

Routes Definition

routes.py defines HTTP endpoints:
app/catalogs/colors/routes.py
from . import colors_bp
from .forms import ColorForm
from .services import ColorService

@colors_bp.route('/create', methods=['GET', 'POST'])
def create_color():
    # Handle form and call service
    pass
3

Business Logic

services.py contains domain logic:
app/catalogs/colors/services.py
class ColorService:
    @staticmethod
    def create(data: dict) -> dict:
        # Validation and business rules
        # Database operations
        pass
4

Form Validation

forms.py defines WTForms:
app/catalogs/colors/forms.py
from flask_wtf import FlaskForm
from wtforms.validators import DataRequired

class ColorForm(FlaskForm):
    name = StringField('Nombre', validators=[DataRequired()])

Request Flow

Understanding how a request flows through the application:
1

Request Received

Browser sends HTTP request to Flask route in routes.py
2

Form Processing

Route validates submitted form using WTForms
3

Business Logic

Route calls service method with validated data
4

Database Operation

Service uses models to query/update database via SQLAlchemy
5

Response Rendering

Route renders Jinja2 template with data and returns HTML

Core Components

Application Factory

The create_app() function in app/__init__.py creates and configures the Flask application:
app/__init__.py
def create_app():
    app = Flask(__name__)
    
    # Load configuration
    app.config.from_object(Config)
    
    # Initialize extensions
    db.init_app(app)
    migrate.init_app(app, db)
    csrf.init_app(app)
    
    # Register error handlers
    register_error_handlers(app)
    
    # Register blueprints
    from .catalogs.colors import colors_bp
    app.register_blueprint(colors_bp, url_prefix='/colors')
    
    return app

Extensions

Flask extensions are initialized in app/extensions.py:
app/extensions.py
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from flask_wtf.csrf import CSRFProtect

db = SQLAlchemy()          # Database ORM
migrate = Migrate()        # Database migrations
csrf = CSRFProtect()       # CSRF protection

Configuration

Application configuration in config.py:
config.py
class Config:
    # Database configuration
    DB_USER = os.getenv("DB_USER")
    DB_PASSWORD = os.getenv("DB_PASSWORD")
    DB_HOST = os.getenv("DB_HOST")
    DB_PORT = os.getenv("DB_PORT")
    DB_NAME = os.getenv("DB_NAME")
    
    SQLALCHEMY_DATABASE_URI = (
        f"mysql+pymysql://{DB_USER}:{DB_PASSWORD}@{DB_HOST}:{DB_PORT}/{DB_NAME}"
    )
    
    # Security
    SECRET_KEY = os.getenv("SECRET_KEY")
    SQLALCHEMY_TRACK_MODIFICATIONS = False

Database Models

Models define the database schema using SQLAlchemy ORM. Example from app/models/color.py:
app/models/color.py
class Color(db.Model):
    __tablename__ = 'colors'
    
    id_color = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(50), nullable=False, unique=True)
    active = db.Column(db.Boolean, nullable=False, default=True)
    
    created_at = db.Column(db.TIMESTAMP, server_default=func.current_timestamp())
    updated_at = db.Column(db.TIMESTAMP, server_onupdate=func.current_timestamp())
    deleted_at = db.Column(db.TIMESTAMP, nullable=True)
    
    def to_dict(self) -> dict:
        return {
            "id_color": self.id_color,
            "name": self.name,
            "active": self.active
        }

Template Organization

Templates are organized by module with a shared base template:
  • base.html - Shared layout with navigation and flash messages
  • {module}/list.html - List/index view
  • {module}/create.html - Create form
  • {module}/edit.html - Edit form
  • errors/error.html - Generic error page

Next Steps

Coding Conventions

Learn the project’s coding standards

Templates Guide

Work with Jinja2 templates

Forms Guide

Create and validate forms

Deployment

Deploy to production

Build docs developers (and LLMs) love