Enrutamiento tradicional en Django#

Este es el séptimo artículo de la serie tutorial de Django Ninja. Hemos llegado al Capítulo 3 de la serie.
El Capítulo 3 es la parte principal de toda la serie, ya que presentaremos la parte central de Django Ninja: la API.
He dividido este capítulo en tres secciones:
- Sección 1: Enrutamiento (Router)
- Sección 2: Solicitudes (Request)
- Sección 3: Respuestas (Response)
El Capítulo 3 es también el único capítulo dividido en secciones.
Ahora entramos a la primera sección: Enrutamiento. Primero, conozcamos los puntos clave de aprendizaje de esta sección.
Proyecto de ejemplo en GitHub#
Puntos clave de esta sección#
Esta sección consta de dos artículos en total, que son:
- Entrega 7: Enrutamiento (I) Enfoque tradicional de rutas en Django
- Entrega 8: Enrutamiento (II) Configuración de rutas en Django Ninja
¿Por qué organizarlo de esta manera? Porque los endpoints y el enrutamiento son el punto de partida de las solicitudes API.
Sin ellos, tus funciones view ni siquiera podrían recibir solicitudes, y mucho menos responderlas. Por lo tanto, la configuración del enrutamiento debe ser lo primero, sirviendo como la puerta de entrada para aprender el desarrollo de API.
En cuanto a los «endpoints», puedes pensarlos simplemente como las URL donde se encuentra la API.
Propósito de este artículo#
En segundo lugar, la configuración de rutas en Django Ninja es muy diferente de la configuración tradicional en Django o Django REST framework (en adelante, DRF); en cambio, es más cercana al estilo de FastAPI o Flask.
Este fue el primer obstáculo con el que me encontré al aprender Django Ninja (después de todo, escribí DRF durante 2 años 😅), por lo que decidí dividirlo en dos artículos para explicarlo en detalle, ayudándote a construir una base sólida y reducir la confusión.
El enfoque de este artículo es presentar la configuración tradicional de rutas en Django. ¡Comencemos!
¿Qué es el enrutamiento (Routers)?#
El enrutamiento (Router) es uno de los componentes clave de un servicio web. Se encarga de mapear las solicitudes HTTP enviadas por el cliente (normalmente el navegador) hacia la lógica de procesamiento correcta.
En Django, el enrutamiento es el mecanismo que decide «qué solicitud debe ser procesada por cuál View».
Cuando un cliente visita una URL específica (a la que llamamos «endpoint»), el servidor de Django encuentra la función de procesamiento correspondiente según esa URL para ejecutar una lógica determinada.
Este proceso de «mapeo (mapping)» es la responsabilidad central del enrutamiento.
Introducción al enrutamiento en Django#
El mecanismo de enrutamiento de Django gestiona la estructura de rutas a diferentes niveles principalmente a través de la configuración en urls.py, e integra y organiza todos los endpoints mediante rutas de primer y segundo nivel.
Hasta aquí, ya hemos mencionado los tres elementos clave del enrutamiento en Django:
- Rutas de primer nivel
- Rutas de segundo nivel
urls.py
A continuación los presentamos.
Rutas de primer nivel#
Las rutas de primer nivel son rutas a «nivel de proyecto», y generalmente se encuentran en el archivo urls.py dentro del directorio del proyecto Django (es decir, el directorio NinjaForum en el proyecto de ejemplo).
Se utilizan principalmente para añadir un «prefijo de ruta» unificado para cada app de Django, e integrar las rutas provenientes de todas las apps.
Tomando este proyecto como ejemplo, podría verse así:
# NinjaForum/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('posts/', include('post.urls')), # Maneja las rutas de la app post
path('users/', include('user.urls')), # Maneja las rutas de la app user
]
Aquí, urlpatterns es la ruta de primer nivel de Django. Dirige las rutas /posts/ y /users/ a las rutas de segundo nivel de las apps post y user respectivamente, sirviendo como prefijo unificado para las rutas de segundo nivel de cada app.
Rutas de segundo nivel#
Las rutas de segundo nivel son gestionadas de forma independiente por cada app de Django. Corresponden directamente a las funciones view de la propia app:
# post/urls.py
from django.urls import path
from post import views
urlpatterns = [
path('', views.get_posts),
path('<int:post_id>/', views.post_detail),
]
Tras recombinar la lógica de las rutas de primer y segundo nivel, los endpoints reales de las rutas a nivel de app anteriores son:
/posts/: Obtener todas las publicaciones./posts/<int:post_id>/: Obtener los detalles de una publicación específica.
Esta estructura jerárquica de rutas no solo hace que las URL estén más organizadas, sino que también vuelve más modular la funcionalidad de las distintas apps.
Por ejemplo, si quisiéramos añadir una API para «obtener datos de usuario» en la app user, solo necesitaríamos crear la ruta correspondiente en el urls.py de la app user, sin tener que modificar la configuración de rutas a nivel de proyecto.
Diagrama de arquitectura del proyecto#
Visto desde una perspectiva panorámica, podría ser aún más claro.
En lo que respecta al enrutamiento tradicional de Django, la estructura de directorios y archivos de todo el proyecto de ejemplo es la siguiente (omitiendo partes no relevantes):
├── NinjaForum
│ ├── urls.py # Rutas de primer nivel del proyecto
│ ├── ...
├── post
│ ├── urls.py # Rutas de segundo nivel de la app
│ ├── ...
├── user
│ ├── urls.py # Rutas de segundo nivel de la app
│ ├── ...
├── ...
Esta estructura es muy común en los proyectos de Django y también es la práctica estándar en DRF.
Las rutas de primer nivel del proyecto se encargan del punto de entrada global, mientras que las rutas de segundo nivel se encargan de asociar las funciones view de la app. Este diseño hace que la arquitectura del proyecto sea más modular y escalable.
Ventajas y desventajas del enrutamiento tradicional en Django#
El mecanismo de enrutamiento tradicional de Django organiza y define rutas URL completas (endpoints) a través de urls.py a nivel de proyecto y de app. Este diseño tiene sus ventajas y desventajas; exploremos los pros y los contras.
Ventaja: una lista clara de endpoints#
Una gran ventaja del enrutamiento tradicional de Django es que todos los endpoints y rutas están concentrados en urls.py. Esto significa que los desarrolladores pueden ver de un vistazo todos los endpoints de la API actuales (para esa app), por ejemplo:
# urls.py a nivel de app
from django.urls import path
from . import views
urlpatterns = [
path('home/', views.home, name='home'),
path('about/', views.about, name='about'),
path('contact/', views.contact, name='contact'),
]
urls.py actúa como un catálogo de rutas, claro a simple vista.
Desventaja: comparar endpoints y funciones view requiere alternar de un lado a otro#
Como se mencionó anteriormente, el enrutamiento es responsable de conectar los endpoints con las funciones view.
Dado que cada endpoint requiere una función view correspondiente, y las funciones view correspondientes suelen colocarse en views.py.

Esto genera un problema: los desarrolladores necesitan alternar de un lado a otro entre urls.py y views.py para comprender completamente un endpoint y la lógica de implementación detrás de él.
Esta falta de «intuitividad» no solo aumenta la carga cognitiva durante el desarrollo, sino que también facilita la aparición de errores al modificar la API.
Además, a medida que el proyecto se expande, la lista de endpoints en urls.py se vuelve cada vez más larga; encontrar la función view correspondiente se vuelve tedioso y consume tiempo, aumentando aún más la posibilidad de cometer errores.
Resumen#
En este artículo, profundizamos en el diseño de rutas del Django tradicional y exploramos sus ventajas y desventajas.
Este diseño estructurado hace que la gestión de rutas sea más modular, pero también genera problemas de mantenimiento y lectura en proyectos de gran tamaño.
A continuación, exploraremos cómo Django Ninja ofrece un mecanismo de rutas más limpio y lo compararemos con el enrutamiento tradicional de Django.
The Django Ninja Way#
Django Ninja adopta un enfoque más moderno para manejar rutas y funciones view: combina estrechamente ambas, proporcionando un medio más intuitivo para definir endpoints de API. (En realidad, todos aprendieron de Flask ☺️).
No solo reduce drásticamente la necesidad de cambiar entre diferentes archivos, sino que también mejora la legibilidad y mantenibilidad del código.
En el próximo artículo, conozcamos el mecanismo de rutas de Django Ninja y veamos cómo resuelve estos problemas.