Actualizado el domingo, 17 marzo, 2024

Las quejas más comunes de los nuevos en Django son «es demasiado difícil de entender» o «es demasiado complejo». Incluso puedes estar pensando esto tú mismo en este momento.

En el nivel fundamental, Django no es complicado. Sí, tiene sus peculiaridades y, sí, los grandes proyectos de Django pueden ser bestias muy complejas, pero en pocas palabras: Django es un framework lógicamente estructurado construido sobre el lenguaje de programación más fácil de aprender disponible (Python).

Como educador, he pasado incontables horas tratando de averiguar por qué las personas encuentran a Django complejo y difícil de aprender. Pensar en esto me ha llevado a cometer la herejía # 1: no es tu culpa, solo lo hemos estado enseñando mal.

¿Recuerdas todos los libros y tutoriales que comienzan con «Django es un framework Modelo-Vista-Controlador (MVC)…»? (Esto es cortar y pegar de uno de mis libros, así que soy tan culpable como cualquiera en esto).

Afirmar por adelantado que Django es un framework MVC obtiene una de dos respuestas:

  1. Los principiantes dicen «¿Qué diablos es MVC? *gemido*. ¡Supongo que esa es una cosa más que tengo que aprender!»
  2. Los programadores más experimentados dicen «¡Ajá! Es como Framework X».

En ambos casos, están casi completamente equivocados.

Django es un framework débilmente acoplado

Si puedes complacerme un minuto y purgar tu cerebro de tus acrónimos de tres letras (TLA) favoritos, hay una manera más fácil de entender esto.

El primer paso es entender que Django no es el resultado de un ejercicio académico, ni es la idea de cool de algún gurú: los creadores de Django diseñaron Django para resolver un conjunto particular de problemas en una organización de noticias ocupada y compleja. En el centro de este conjunto de problemas había tres necesidades muy diferentes:

  1. Los chicos de datos (y chicas) necesitaban una interfaz común para trabajar con fuentes de datos, formatos y software de base de datos dispares.
  2. Los equipos de diseño necesitaban gestionar la experiencia del usuario con las herramientas que ya tenían (HTML, CSS, JavaScript, etc.).
  3. Los codificadores incondicionales requerían un framework que les permitiera implementar cambios en el sistema rápidamente y mantener a todos contentos.

Crucial para hacer que todo esto funcionara era garantizar que cada uno de estos componentes centrales (datos, diseño y lógica empresarial) pudiera administrarse de forma independiente, o usar el lenguaje informático correcto: el framework tenía que emplear un acoplamiento flexible..

Ahora, es importante entender que no estoy tratando de decir que Django está haciendo algo mágico o nuevo aquí, ni los problemas que enfrentaron los creadores de Django fueron únicos. Los creadores de Django son tipos brillantes, y ciertamente sabían que MVC era un patrón de diseño bien establecido que ayudaría a resolver sus problemas.

Mi punto es que es muy poco probable que alguno de ellos haya dicho: «Esperen chicos, necesitamos cambiar este código porque Wikipedia dice que un controlador debería …».

No necesita obsesionarse con la semántica: puede olvidarse con seguridad de los confusos TLAs y si Django es como Framework X y concentrarse en lo que es Django.

La arquitectura de Django consta de tres partes principales:

  • La Parte 1 es un conjunto de herramientas que facilitan mucho el trabajo con datos y bases de datos.
  • La Parte 2 es un sistema de plantillas de texto plano adecuado para no programadores; y
  • La Parte 3 es un framework que maneja la comunicación entre el usuario y la base de datos, y automatiza muchas de las partes dolorosas de la administración de un sitio web complejo.

Las partes 1 y 2 se pueden relacionar instantáneamente (ver Figura 3.1):

  • Los modelos Django son las herramientas que utilizamos para trabajar con datos y bases de datos.
  • Las plantillas de Django proporcionan un sistema de plantillas de texto plano fácil de diseñar.

Pero, ¿qué pasa con la Parte 3? Te oigo preguntar, ¿no es ese el controlador o una vista de Django?

Bueno, no. Lo que me lleva a la herejía #2:

Una vista de Django no es un controlador

Echa un vistazo a la Figura 3.1, ¿te parece familiar?

Figura 3.1: El diagrama algo engañoso de Django MTV.

Este es uno de mis diagramas, pero hay muchas versiones similares por ahí. Una forma común de explicar la arquitectura de Django en términos de MVC es describirla como un Modelo-Plantilla-Vista (MTV) o Modelo-Vista-Plantilla (MVT). No hay diferencia entre MTV y MVT, son dos formas diferentes de describir lo mismo, lo que aumenta la confusión.

La parte engañosa de este diagrama es la vista. La vista en Django se describe con mayor frecuencia como equivalente al controlador en MVC, pero no lo es, sigue siendo la vista.

La figura 3.2 es una variación de la figura 3.1 para ilustrar mi punto.

Figura 3.2: Una visión ligeramente diferente de la «pila» de Django en MTV.

Observe cómo he trazado una línea entre el lado del cliente y el del servidor. Como todas las arquitecturas cliente/servidor, Django utiliza objetos de solicitud y respuesta para comunicarse entre el cliente y el servidor. Como Django es un framework web, estamos hablando de objetos de solicitud y respuesta HTTP.

Entonces, en este proceso simplificado, la vista recupera datos de la base de datos a través del modelo, los formatea, los agrupa en un objeto de respuesta HTTP y los envía al cliente (navegador).

En otras palabras, la vista presenta el modelo al cliente como una respuesta HTTP. Esta es también la definición exacta de la vista en MVC, o para citar a Wikipedia (no es la fuente más definitiva, lo sé, pero lo suficientemente cerca):

«La vista significa la presentación del modelo en un formato particular»

Tratar de doblar la definición de una visión de Django para que se ajuste a un punto de vista particular conduce inevitablemente a una de dos cosas:

  1. El programador confundido pone todo en el módulo de vistas; o
  2. El programador confundido dice «¡Django es demasiado difícil!», y ve la televisión en su lugar

Así que alejándonos de nuestras M’s y T’s, V’s y C’s, la Figura 3.3 presenta una visión más holística de la arquitectura de Django.

Figura 3.3: Una visión más holística de la arquitectura de Django.

El primer punto de confusión que podemos aclarar es dónde poner una función o clase en particular:

¿La función/clase devuelve una respuesta?

  • SÍ, es una vista. Póngalo en el módulo de vistas (views.py).
  • NO, no es una vista, es lógica de la aplicación. Póngalo en otro lugar (somewhere_else.py).

Discutiremos la parte de otro lugar en la siguiente sección de este capítulo.

El siguiente punto a tener en cuenta es que el framework Django encapsula el modelo, la lógica de vista y la lógica de negocios. En algunos tutoriales, se dice que el framework Django es el controlador, pero eso tampoco es cierto: el framework Django puede hacer mucho más que responder a la entrada del usuario e interactuar con los datos.

Un ejemplo perfecto de esta potencia adicional es el middleware de Django, que se encuentra entre la vista y el lado del cliente. El middleware de Django realiza comprobaciones críticas de seguridad y autenticación antes de enviar la respuesta al navegador.

Entonces, volviendo a las dos respuestas confusas del comienzo del capítulo:

  1. Principiantes: no, no tienen que aprender sobre MVC porque es más que probable que los confunda y genere más preguntas que respuestas.
  2. Programadores: no, Django no es como Framework X, y tratar de pensar que lo es, es probable que te confunda y genere más preguntas que respuestas.

Ahora que tenemos eso fuera del camino, echemos un vistazo a la estructura de un proyecto de Django.

Estructura del proyecto Django

Django no requiere que construyas aplicaciones web de ninguna manera en particular. De hecho, miles de millones de electrones han sido sacrificados discutiendo la mejor manera de estructurar un proyecto de Django. Todos somos programadores pragmáticos aquí, así que no jugaremos ese juego.

Sin embargo, Django tiene una forma predeterminada de hacer las cosas, y hay una lógica subyacente definida que debe comprender para convertirse en un programador profesional de Django.

La unidad fundamental de una aplicación web Django es un proyecto Django. Un proyecto de Django comprende una o más aplicaciones de Django (Figura 3.4)

Figura 3.4: Estructura del proyecto de Django.

Una aplicación Django es un paquete autónomo que solo debe hacer una cosa. Por ejemplo, un blog, una aplicación de membresía o un calendario de eventos. Observe que en la parte inferior de la figura 3.4, hay un paquete adicional llamado Django Apps.

Este es otro caso en el que la lógica de Django se transmite a través del framework: Django en sí es una colección de aplicaciones, cada una diseñada para hacer una cosa. Con las aplicaciones integradas de Django, todas están diseñadas para hacerte la vida más fácil, lo cual es algo bueno.

Aunque las aplicaciones integradas son invisibles en el árbol del proyecto, puedes verlas en el archivo settings.py:

# ...\myclub_project\myclub_site\myclub_site\settings.py

# partial listing

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

Puedes ver que Django ha agregado varias aplicaciones a tu proyecto automáticamente. También hay muchas otras aplicaciones integradas de Django que puede agregar a la lista INSTALLED_APPS. Cuando agrega sus aplicaciones a un proyecto de Django, también agrega un vínculo a la clase de configuración de la aplicación a esta lista.

Puedes ver esta lógica en lo que Django ha creado para ti hasta ahora. Abra la carpeta \myclub_project. La estructura de carpetas debería tener un aspecto similar al siguiente:

# ...\my_clubproject

\env_myclub
\myclub_site        <= This is your Django project
    \myclub_site    <= This is a Django app
    db.sqlite3      <= Your project database
    manage.py       <= Django project management utility

Examinemos estos archivos y carpetas con más detalle:

  • La carpeta env_myclub es donde Django almacena los archivos del entorno virtual. En general, debe dejar todo dentro de esta carpeta solo.
  • La carpeta myclub_site externa es tu proyecto de Django. Django creó esta carpeta y su contenido cuando ejecutó el comando startproject en el último capítulo. A Django no le importa el nombre de la carpeta, por lo que puede cambiarle el nombre a algo significativo para usted.
  • Dentro de la carpeta myclub_site externa hay dos archivos:
    • db.sqlite3. La base de datos creada al ejecutar el comando migrate; y
    • manage.py. Una utilidad de línea de comandos para ejecutar comandos de Django desde dentro de su proyecto.
  • La carpeta myclub_site interna es la aplicación del sitio web de Django. Esta es la única aplicación que Django crea automáticamente para usted. Debido a que Django es un framework web, asume que desea una aplicación de sitio web.

Esto debería tener más sentido a estas alturas, pero apuesto a que hay una cosa que todavía es un poco confusa: las dos carpetas myclub_site.

Una queja muy común de los programadores nuevos en Django es lo confuso que es saber en qué carpeta deben trabajar cuando hay dos carpetas con el mismo nombre. Django no está solo con esta convención: los entornos de desarrollo integrado (IDE) como Visual Studio crean una carpeta de proyecto y una carpeta de aplicación con el mismo nombre. Pero solo porque sea común, eso no significa que no sea confuso.

Como dije hace un momento, a Django no le importa cómo llames esta carpeta, así que cometamos la herejía # 3, rompiendo trece años de convención tutorial de Django mientras estamos en eso, ¡y cambiemos el nombre de la carpeta!

Aquí, lo estamos renombrando a «myclub_root».

Una vez que haya realizado el cambio, su estructura de carpetas debe ir de esto:

\myclub_project
    \myclub_site
        \myclub_site

A esto:

\myclub_project
    \myclub_root
        \myclub_site

Ahora que nos hemos ocupado de esa fuente de confusión, echemos un vistazo dentro de la aplicación de sitio web myclub_site que Django creó para nosotros:

# \myclub_project\myclub_root\

\myclub_site
    __init__.py
    asgi.py # Django 3 only
    settings.py
    urls.py
    wsgi.py

Mirando más de cerca estos archivos:

  • El archivo __init__.py indica a Python que esta carpeta (su aplicación Django) es un paquete de Python.
  • asgi.py permite que los servidores web compatibles con ASGI sirvan a su proyecto.
  • settings.py contiene la configuración de su proyecto Django. Cada proyecto de Django debe tener un archivo de configuración. Por convención, Django lo pone en la aplicación de su sitio web, pero no tiene que vivir allí. Hay defensores de otras estructuras como mencioné anteriormente, pero aquí estamos usando el valor predeterminado.
  • urls.py contiene configuraciones de URL de nivel de proyecto. De forma predeterminada, contiene un único patrón de URL para el administrador. Cubriremos más sobre las URL más adelante en el capítulo, y con gran detalle en el Capítulo 5.
  • wsgi.py permite que los servidores web compatibles con WSGI sirvan a su proyecto.

Ahora que hemos echado un buen vistazo a la estructura básica de un proyecto Django, es hora de dar el siguiente paso y agregar nuestra propia aplicación Django.

Creando tus propias aplicaciones Django

Es posible que haya notado que hasta ahora no hay un código de programa real en su proyecto. Hay un archivo de configuración con información de configuración, un archivo de URL casi vacío y una utilidad de línea de comandos que inicia un sitio web que no hace mucho.

Esto se debe a que para crear un sitio web de Django que funcione, debe crear aplicaciones de Django. Una aplicación Django (o aplicación para abreviar) es donde se realiza el trabajo. Las aplicaciones son una de las características asesinas de Django. No solo le permiten agregar funcionalidad a un proyecto de Django sin interferir con otras partes del proyecto, sino que las aplicaciones están diseñadas para ser portátiles para que pueda usar una aplicación en múltiples proyectos.

Entonces, creemos nuestra primera aplicación personalizada de Django. Nuestro sitio web del club social necesita un calendario de eventos para mostrar los próximos eventos del club, por lo que estamos creando una aplicación de Django llamada events..

Inicie su entorno virtual de Python, cambie a la carpeta \myclub_root y ejecute el comando:

python manage.py startapp events

Así es como debería verse la salida del shell de comandos:

(env_myclub) ...> cd myclub_root
(env_myclub) ...\myclub_root> python manage.py startapp events
(env_myclub) ...\myclub_root>

Una vez que haya creado su aplicación, debe decirle a Django que la instale en su proyecto. Esto es fácil de hacer: dentro de su archivo settings.py hay una lista llamada INSTALLED_APPS. Esta lista contiene todas las aplicaciones instaladas en su proyecto Django. Django viene con algunas aplicaciones preinstaladas, solo tenemos que agregar su nueva aplicación de events a la lista (cambiar en negrita):

1 INSTALLED_APPS = [
2     'events.apps.EventsConfig',
3     'django.contrib.admin',
4     # more apps
5 ]

Dentro de cada aplicación, Django crea un archivo, apps.py, que contiene una clase de configuración que lleva el nombre de su aplicación. Aquí, la clase se denomina EventsConfig. Para registrar nuestra aplicación con Django, debemos apuntar a la clase EventsConfig, que es lo que estamos haciendo en la línea 2 de nuestra lista de INSTALLED_APPS modificada.

Si se lo preguntaba, EventsConfig contiene dos opciones de configuración de forma predeterminada: el nombre de la aplicación («eventos») y el tipo de datos de campo automático predeterminado.

Numeración de líneas en ejemplos de código

A lo largo del libro, utilizo la numeración de líneas para que sea más fácil para usted seguir las explicaciones.

Como a menudo uso fragmentos de código de los archivos de aplicación, la numeración de línea en el ejemplo no es la misma que la numeración de línea en el archivo de código fuente real.

Ahora echemos un vistazo dentro de la carpeta \myclub_root para ver lo que Django ha creado para nosotros:

\events
    \migrations
    __init__.py
    admin.py
    apps.py
    models.py
    tests.py
    views.py
  • La carpeta de migraciones es donde Django almacena las migrations o los cambios en su base de datos. No hay nada aquí de lo que deba preocuparse en este momento.
  • __init__.py le dice a Python que su aplicación events es un paquete.
  • admin.py es donde registra los modelos de su aplicación con la aplicación de administración Django.
  • apps.py es un archivo de configuración común a todas las aplicaciones de Django.
  • models.py es el módulo que contiene los modelos de la aplicación.
  • tests.py contiene procedimientos de prueba que se ejecutan al probar la aplicación.
  • views.py es el módulo que contiene las vistas de la aplicación.

Ahora que tenemos una imagen completa de un proyecto de Django, también podemos responder a la pregunta anterior en el capítulo: «bueno, si no es una vista, ¿a dónde va?»

Cuando tienes código que no es una vista, creas un nuevo módulo de Python (archivo .py) dentro de tu aplicación y colocas funciones y clases relacionadas dentro del archivo. Tenga en cuenta el énfasis en relacionado. Si tiene un montón de funciones que proporcionan utilidades de administración de bases de datos, por ejemplo, colóquelas todas en un archivo. Las funciones y clases no relacionadas con la administración de bases de datos deben ir en otro archivo. También debe tratar de ser descriptivo al nombrar módulos; después de todo, es más sensato poner las funciones de su base de datos en un archivo llamado db_utils.py que en un archivo llamado monkeys.py …

Al crear nuevos módulos para su proyecto Django, también debe considerar el alcance. Si bien agregar módulos personalizados a las aplicaciones es mucho más común (y más portátil), puede tener módulos a nivel de proyecto (por ejemplo, manage.py de Django) y módulos a nivel de sitio. En este último caso, los módulos personalizados deben ir en la misma carpeta que el archivo settings.py.

El último par de puntos puede parecer cegadoramente obvio, pero es importante entender que, si bien Django tiene una lógica predeterminada para su estructura, nada está escrito en piedra. Django es flexible y le permite expandir y cambiar la estructura de su proyecto para adaptarse a la lógica de su aplicación web.

Ahora que tenemos una comprensión profunda de la estructura de los proyectos y aplicaciones de Django, la siguiente pregunta obvia, dado que estamos construyendo aplicaciones web es «¿cómo navegamos por un proyecto de Django?»

Para responder a esta pregunta, necesitamos revisar la pieza final del rompecabezas del panorama general de Django: las configuraciones de URL.

URLconfs—Navegador de Django

Hay una última pieza en el rompecabezas del framework de Django: la ruta de comunicación crítica que hace coincidir una solicitud en el lado del cliente con un recurso de proyecto (las flechas entre la vista y la plantilla en la Figura 3.3). Como todas las aplicaciones web, Django utiliza localizadores uniformes de recursos (URL) para hacer coincidir el contenido con una solicitud.

El paquete de URL de Django proporciona docenas de funciones y clases para trabajar con diferentes formatos de URL, resolución de nombres, manejo de excepciones y otras urls navegación. Sin embargo, en su forma más básica, le permite asignar una URL a una función o clase dentro de su proyecto Django.

Una configuración de URL de Django (o URLconf para abreviar) hace coincidir una URL única con un recurso de proyecto. Puedes pensar que es como hacer coincidir el nombre de una persona con su dirección. Excepto en Django, no estamos haciendo coincidir una dirección, estamos haciendo coincidir una ruta de Python usando la notación de puntos de Python.

Suponiendo que no esté familiarizado con la notación de puntos, es un modismo común en la programación orientada a objetos. Me gusta pensar en el punto como un punto porque el punto apunta a algo. Con Python, el operador punto apunta al siguiente objeto de la cadena de objetos.

En las clases de Django, la cadena de objetos es así:

package.module.class.method

O con funciones:

package.module.function.attribute

Algunos ejemplos de la vida real:

  • forms.Form apunta a la clase Form del paquete forms.
  • events.apps.EventsConfig apunta a la clase EventsConfig en el subpaquete apps del paquete events (es decirapps apps.py de la aplicación events).
  • django.conf.urls apunta al paquete urls dentro del paquete conf dentro de Django, ¡que también es un paquete de Python!

Esto a veces puede ser un poco confuso, pero si recuerdas unir los puntos (lo siento, un mal juego de palabras allí), generalmente puedes averiguar a qué se refiere el operador de puntos.

Con una URLconf, la ruta apunta a una función o clase dentro de un módulo (archivo .py). Veamos nuestro diagrama del proyecto Django de nuevo (Figura 3.5).

Figura 3.5: Encontrar funciones y clases con URLconfs de Django.

Para crear una URLconf, usamos la función path() La primera parte de la función es la URL, por lo que en la Figura 3.5 la URL es app1/. La función path()() asigna esta URL a app1.views.some_view().

Suponiendo que la dirección de su sitio es http://www.mycoolsite.com, en inglés simple estamos diciendo:

«Cuando alguien navegue a http://www.mycoolsite.com/app1/, ejecute la función some_view() dentro del archivo views.py de app1«.

Tenga en cuenta que una URL no tiene que asignarse a una vista, puede asignarse a cualquier módulo de su aplicación Django. Por ejemplo, puede tener un conjunto de sensores ambientales inalámbricos que devuelven datos al servidor. Puede tener un módulo personalizado llamado sensors.py que tiene una función o clase para registrar los datos del sensor en su base de datos, todo sin tocar una vista.

Y eso es todo lo que hay que hacer. Por supuesto, URLconfs puede hacer mucho más que asignar una URL estática a una función o clase, pero si puede comprender los conceptos básicos, que el sistema de navegación increíblemente rápido y poderoso de Django se basa en el simple concepto de hacer coincidir una URL con un recurso, entonces tiene todo lo que necesita para unir todas sus aplicaciones Django en un proyecto web navegable.

Una nota final sobre la escritura de aplicaciones de Django

Una pregunta común e inevitable surge una vez que entiendes la estructura básica de Django:

«¿Por dónde empiezo? ¿Debo empezar escribiendo mis modelos, las configuraciones de URL, mis vistas? ¿O qué?»

Bueno, aquí está tu herejía final para el capítulo: no importa.

A algunas personas les gusta comenzar construyendo todos los modelos para que puedan ver cómo se ve la estructura de datos; Otros prefieren construir primero el diseño visual, por lo que comienzan con plantillas. A otros les gustaría tener el framework de comunicación básico en su lugar, por lo que comienzan con vistas y URLconfs. Otros comenzarán en cualquier punto que parezca lógico para el proyecto.

Siendo pragmático hasta los huesos, generalmente estoy en el último grupo. Trato de no obsesionarme con lo que alguien más piensa que es la forma correcta o incorrecta de hacer las cosas y trato de encontrar la forma más simple y rápida de lograr el resultado que quiero. También me gusta trabajar de forma incremental, comenzando poco a poco, obteniendo el flujo correcto y construyendo sobre él para crear la aplicación completa. Este enfoque significa que inevitablemente termino saltando de un elemento a otro a medida que la aplicación crece.

Tu cerebro está conectado de manera diferente al mío y a cualquier otro programador. Esto es algo bueno. Solo recuerde, un comienzo imperfecto para un proyecto es mucho mejor que no comenzar en absoluto. Haz lo que funcione para ti.

Resumen del capítulo

En este capítulo, le di una descripción general de alto nivel de cómo se estructuran los proyectos de Django, cómo funciona cada componente con otras partes de Django para crear una aplicación web y cómo crear una aplicación Django.

En el próximo capítulo, comenzaremos a sumergirnos en el funcionamiento interno de los módulos centrales de Django explorando los fundamentos de los modelos de Django.

Descarga de libro Phyton para todos (5 descargas )