FastAPI vs Django vs Laravel vs Flask: ¿Cómo se organizan las RUTAS?

- Andrés Cruz - EN In english

Video thumbnail

Índice de contenido

Vamos a hablar sobre los tipos de rutas o las formas en las cuales tenemos para definir nuestras rutas. Para eso, voy a comparar los frameworks de Flask, FastAPI, Django y Laravel, que son los con los cuales yo realmente trabajo. Básicamente, estos se dividen en dos tipos.

  • Flask y FastAPI: En el caso de Flask, tenemos los blueprints, que son decoradores que colocamos directamente al endpoint. Por otro lado, FastAPI —que se inspiró en Flask por ser también un microframework— lleva esto al siguiente nivel. Utiliza decoradores para definir sus endpoints, pero también permite especificar si los métodos son síncronos o asíncronos y permite incluir validaciones directamente en la definición de la ruta. En este caso, FastAPI es considerado un framework más moderno porque permite agrupar parámetros de forma más estructurada que Flask.
# routes/products.py
from flask import Blueprint

products_bp = Blueprint('products', __name__, url_prefix='/products')

@products_bp.route('/<int:product_id>', methods=['GET'])
def get_product(product_id):
    return {"id": product_id, "name": "Laptop"}

# app.py (Registro)
from flask import Flask
from routes.products import products_bp

app = Flask(__name__)
app.register_blueprint(products_bp)

#--------------FASTAPI
# routers/products.py
from fastapi import APIRouter

router = APIRouter(prefix="/products", tags=["Products"])

@router.get("/{product_id}")
async def get_product(product_id: int):
    return {"id": product_id, "name": "Laptop"}

# main.py (Registro)
from fastapi import FastAPI
from routers.products import router as products_router

app = FastAPI()
app.include_router(products_router)
  • Django y Laravel: Django separa el archivo de rutas de la lógica de las vistas. La implementación se encuentra en archivos llamados urls.py, que funcionan como módulos dentro de cada aplicación. Aunque la definición es similar a Flask y FastAPI (URI, método y nombre), lo disruptivo aquí es que manejamos un archivo aparte para no "ensuciar" el endpoint. Laravel lleva esto al siguiente nivel con una organización mucho más estructurada, permitiendo encadenamientos, prefijos, middlewares, controladores y múltiples formas de agrupación.
  • # products/urls.py (Dentro de la app 'products')
    from django.urls import path
    from .views import get_product
    
    urlpatterns = [
        path('<int:product_id>/', get_product, name='product-detail'),
    ]
    
    # config/urls.py (Archivo global de rutas)
    from django.urls import path, include
    
    urlpatterns = [
        path('products/', include('products.urls')),
    ]

En Laravel, aunque podemos definir más, principalmente utilizamos rutas para la web, para la consola y para APIs REST. A mí lo que me gusta de este esquema es que, cuando la aplicación es mediana o grande, tener todas las rutas en un solo archivo dificulta la lectura. En este modelo, tenemos un lugar central para organizarlas, a diferencia de Flask o FastAPI, donde para buscar una ruta tienes que revisar dónde se definió específicamente. La pequeña desventaja es que, obviamente, terminamos con más archivos (por ejemplo, en Django tendrías un archivo de rutas por módulo o aplicación).

// routes/api.php
use App\Http\Controllers\ProductController;
use Illuminate\Support\Facades\Route;

// Opción 1: Grupo de rutas con prefijo
Route::prefix('products')->group(function () {
    Route::get('{id}', [ProductController::class, 'show']);
});

// Opción 2: Controller Route Group (Aún más limpio en Laravel 11/12)
Route::controller(ProductController::class)->prefix('products')->group(function () {
    Route::get('{id}', 'show');
});

Ventajas y Desventajas

El principal problema que tenemos con las rutas en frameworks como FastAPI o Flask es que se dificulta la lectura si queremos ir rápidamente a la definición de un endpoint. Al estar la estructura basada en decoradores, es difícil recordar dónde se definió una ruta específica sin navegar por toda la estructura de módulos. En estos casos, incluso en la extensión oficial de FastAPI, se requiere una herramienta adicional para facilitar la navegación rápida, algo que en Django o Laravel ya viene "gratis" por su arquitectura.

Podemos resumir el enfoque basado en decoradores (ya sea mediante Blueprints o un objeto tipo Routes) con las siguientes características:

  • Ventajas: La proximidad del código. La función y la ruta viven juntas, lo que facilita entender el contexto del endpoint. Además, permite tener el tipado y la documentación automática de forma limpia.
  • Desventajas/Riesgos: El desorden y el acoplamiento. Al no tener una estructura rígida, es fácil romper convenciones en proyectos largos, como nombres de parámetros o estructuras de rutas, lo que dificulta la integración de nuevos desarrolladores.

Por otro lado, el enfoque centralizado y desacoplado (como el de Laravel) funciona como una capa más de separación de responsabilidades. Las reglas, lógica y estructura están en archivos aparte.

  • Ventajas: Es mucho más fácil de mantener. Puedes cambiar una URL o analizar rápidamente qué rutas existen para evitar duplicidades. Para equipos grandes, tener una estructura rígida donde todo está en un solo lugar facilita enormemente la gestión de muchas rutas.
  • Desventajas: A veces, los nombres de los archivos en la estructura de carpetas pueden convertirse en una novela. Por ejemplo, en una estructura organizada para Laravel, podrías tener archivos como post.list, post.save o post.form. El problema de este enfoque es que, al usar nombres tan genéricos, la lectura inicial es clara porque el patrón se repite, pero te obliga a navegar entre muchos archivos para encontrar lo que buscas. Si quieres localizar el listado de cursos, tienes que buscar el archivo list.blade.php y navegar manualmente porque no hay una forma directa de llegar al componente.

Este modelo tiene sus ventajas y desventajas: es más lógico y los archivos son más fáciles de organizar, pero requiere escribir más líneas de código y genera fricción al navegar. En cambio, Laravel ofrece una ventaja adicional al permitir manejar varios archivos de rutas por módulo (web, API, consola, etc.), permitiendo rutas específicas para cada caso.

// Contact
Route::livewire('contact', 'pages::dashboard.contact.list')->name('contact-list');
Route::livewire('contact-services', 'pages::dashboard.contact.service-list')->name('contact-service-list');

Laravel utiliza un esquema con "esteroides" que lo diferencia de otros frameworks como Django. Al tener métodos más expresivos, como las rutas de tipo recursos, se pueden centralizar y gestionar completamente desde un solo lugar sin tener que definir los controladores en otra capa si se usan directamente desde los endpoints. La desventaja principal aquí es la fuerte dependencia del framework; si decides cambiar de tecnología, tendrás que analizar y migrar todo este bloque.

Route::group(['prefix' => 'libros'], function () {
    Route::get('', [PostController::class, 'books'])->name('web-book-list');
    // Route::get('{post_url_clean}', [App\Http\Controllers\Courses\BookController::class, 'show'])->name('web-book-show');
    Route::get('{post:url_clean}', [PostController::class, 'show_book'])->name('web-book-show');
});

Por otro lado, las rutas de Laravel pueden ser un desastre si no se organizan bien, ya que permiten múltiples definiciones y estructuras como redirecciones o callbacks. Si no se gestionan correctamente, las rutas se vuelven kilométricas y difíciles de leer, perdiendo las ventajas del esquema original. Si quieres profundizar en estas tecnologías, puedes visitar mi plataforma de academia para ver los tutoriales organizados paso a paso y acceder al código fuente.

Se analizan las ventajas y desventajas de dos enfoques principales en la definición de rutas: el acoplamiento directo (donde la ruta y el endpoint están juntos) y el enfoque desacoplado (centralizado).


Únete a la comunidad de desarrolladores que han decidido dejar de picar código y empezar a construir productos reales. Recibe mis mejores trucos de arquitectura cada semana:

Acepto recibir anuncios de interes sobre este Blog.