Aspectos destacados de Django: creación de plantillas de líneas de guardado (parte 2)

Publicado: 2022-03-10
Resumen rápido ↬ La creación de código front-end en Django con plantillas y representación del lado del servidor combina el control detallado del HTML escrito a mano con el código limpio y las potentes características de las páginas generadas. Exploramos dividir una página web compleja en varias plantillas, componer esos componentes y aplicar etiquetas y filtros para refactorizar una página HTML simple.

Algunos enfoques sencillos para crear sitios web requieren que un desarrollador escriba cada línea de HTML a mano. En el otro extremo, los creadores de sitios comerciales sin código crean todo el HTML para el usuario automáticamente, a menudo a expensas de la legibilidad del código resultante. La creación de plantillas se encuentra en la mitad de ese espectro, pero más cerca de HTML escrito a mano que, por ejemplo, generar estructura de página en una aplicación de una sola página usando React o una biblioteca similar. Este punto óptimo en el continuo brinda muchos de los beneficios del HTML manual desde cero (código semántico/legible, control total sobre la estructura de la página, carga rápida de la página) y agrega separación de preocupaciones y concisión, todo a expensas de dedicar algo de tiempo a escribir. HTML modificado a mano. Este artículo demuestra el uso de plantillas de Django para escribir páginas complejas.

Espectro HTML. (Vista previa grande)

El tema de hoy se aplica más allá del marco Django. Flask (otro marco web) y Pelican (un generador de sitios estáticos) son solo dos de muchos otros proyectos de Python que utilizan el mismo enfoque para las plantillas. Jinja2 es el motor de plantillas que usan los tres marcos, aunque puede usar uno diferente modificando la configuración del proyecto (estrictamente hablando, Jinja2 es un superconjunto de plantillas de Django). Es una biblioteca independiente que puede incorporar a sus propios proyectos incluso sin un marco, por lo que las técnicas de este artículo son muy útiles.

Piezas anteriores de la serie:

  • Aspectos destacados de Django: Modelos de usuario y autenticación (Parte 1)
  • Aspectos destacados de Django: modelos, administración y aprovechamiento de la base de datos relacional (parte 3)
  • Aspectos destacados de Django: disputa de activos estáticos y archivos multimedia (Parte 4)
¡Más después del salto! Continúe leyendo a continuación ↓

Representación del lado del servidor

Una plantilla es solo un archivo HTML donde el HTML se ha ampliado con símbolos adicionales. Recuerde lo que significa HTML: lenguaje de marcado de hipertexto . Jinja2, nuestro lenguaje de plantillas, simplemente se suma al lenguaje con símbolos de marcado significativos adicionales. Estas estructuras adicionales se interpretan cuando el servidor representa la plantilla para mostrar una página HTML simple al usuario (es decir, los símbolos adicionales del lenguaje de plantillas no se incluyen en la salida final).

La representación del lado del servidor es el proceso de construcción de una página web en respuesta a una solicitud. Django usa la representación del lado del servidor para servir páginas HTML al cliente. Al final de su ejecución, una función de visualización combina la solicitud HTTP, una o más plantillas y, opcionalmente, los datos a los que se accede durante la ejecución de la función para construir una única página HTML que envía como respuesta al cliente. Los datos van desde la base de datos, a través de la vista y hacia la plantilla para llegar al usuario. No se preocupe si esta explicación abstracta no tiene mucho sentido, pasaremos a un ejemplo concreto para el resto de este artículo.

Configuración

Para nuestro ejemplo, tomaremos una página web bastante compleja, la plantilla de administración de Start Bootstrap y reescribiremos el HTML como una plantilla Jinja2. Tenga en cuenta que la biblioteca con licencia del MIT utiliza un sistema de plantillas diferente (basado en JavaScript y Pug) para generar la página que ve, pero su enfoque difiere sustancialmente de las plantillas de estilo Jinja2, por lo que este ejemplo es más una ingeniería inversa que una traducción. de su excelente proyecto de código abierto. Para ver la página web que construiremos, puede echar un vistazo a la vista previa en vivo de Start Bootstrap.

He preparado una aplicación de muestra para este artículo. Para que el proyecto Django se ejecute en su propia computadora, inicie su entorno virtual de Python 3 y luego ejecute los siguientes comandos:

 pip install django git clone https://github.com/philipkiely/sm_dh_2_dashboard.git cd sm_dh_2_dashboard python manage.py migrate python manage.py createsuperuser python manage.py loaddata employee_fixture.json python manage.py runserver

Luego, abra su navegador web y navegue hasta https://127.0.0.1:8000 . Debería ver la misma página que la vista previa, que coincide con la imagen de abajo.

Página principal del tablero. (Vista previa grande)

Debido a que este tutorial se centra en la interfaz, la aplicación subyacente de Django es muy simple. Esto puede parecer mucha configuración para presentar una sola página web y, para ser justos, lo es. Sin embargo, esta configuración también podría admitir una aplicación mucho más robusta.

Ahora, estamos listos para recorrer el proceso de convertir este archivo HTML de 668 líneas en un sitio de Django con la arquitectura adecuada.

Plantillas y herencia

El primer paso para refactorizar cientos de líneas de HTML en código limpio es dividir los elementos en sus propias plantillas, que Django compondrá en una sola página web durante el paso de procesamiento.

Echa un vistazo en páginas/plantillas . Deberías ver cinco archivos:

  • base.html , la plantilla base que extenderá cada página web. Contiene el <head> con el título, importaciones de CSS, etc.
  • navbar.html , el HTML de la barra de navegación superior, un componente que se incluirá cuando sea necesario.
  • footer.html , el código para el pie de página, otro componente que se incluirá cuando sea necesario.
  • sidebar.html , el HTML de la barra lateral, un tercer componente que se incluirá cuando sea necesario.
  • index.html , el código exclusivo de la página principal. Esta plantilla amplía la plantilla base e incluye los tres componentes.

Django ensambla estos cinco archivos como Voltron para representar la página de índice. Las palabras clave que permiten esto son {% block %} , {% include %} y {% extend %} . En base.html :

 {% block content %} {% endblock %}

Estas dos líneas dejan espacio para otras plantillas que amplían base.html para insertar su propio HTML. Tenga en cuenta que el content es un nombre de variable, puede tener varios bloques con diferentes nombres en una plantilla, lo que brinda flexibilidad a las plantillas secundarias. Vemos cómo extender esto en index.html :

 {% extends "base.html" %} {% block content %} <!-- HTML Goes Here --> {% endblock %}

El uso de la palabra clave extends con el nombre de la plantilla base le da a la página de índice su estructura, lo que nos evita copiar el encabezado (tenga en cuenta que el nombre del archivo es una ruta relativa en forma de cadena entre comillas dobles). La página de índice incluye los tres componentes que son comunes a la mayoría de las páginas del sitio. Traemos esos componentes con etiquetas de include de la siguiente manera:

 {% extends "base.html" %} {% block content %} {% include "navbar.html" %} {% include "sidebar.html" %} <!--Index-Specific HTML--> {% include "footer.html" %} <!--More Index-Specific HTML--> {% endblock %}

En general, esta estructura brinda tres beneficios clave sobre la escritura de páginas individualmente:

  • Código SECO (No te repitas)
    Al factorizar el código común en archivos específicos, podemos cambiar el código en un solo lugar y reflejar esos cambios en todas las páginas.
  • Mayor legibilidad
    En lugar de desplazarse por un archivo gigante, puede aislar el componente específico que le interesa.
  • Separación de intereses
    El código para, digamos, la barra lateral ahora tiene que estar en un solo lugar, no puede haber ninguna etiqueta de secuencia de script maliciosa flotando en la parte inferior del código u otra mezcla entre lo que deberían ser componentes separados. Factorizar piezas individuales fuerza esta buena práctica de codificación.

Si bien podríamos ahorrar aún más líneas de código colocando los componentes específicos en la plantilla base.html , mantenerlos separados brinda dos ventajas. La primera es que podemos incrustarlos exactamente donde pertenecen en un solo bloque (esto es relevante solo para el footer.html que va dentro del div principal del bloque de content ). La otra ventaja es que si tuviéramos que crear una página, digamos una página de error 404, y no quisiéramos la barra lateral o el pie de página, podríamos omitirlos.

Estas capacidades son normales para el curso de plantillas. Ahora, pasamos a etiquetas poderosas que podemos usar en nuestro index.html para proporcionar características dinámicas y ahorrar cientos de líneas de código.

Dos etiquetas fundamentales

Esto está muy lejos de ser una lista exhaustiva de etiquetas disponibles. La documentación de Django sobre plantillas proporciona tal enumeración. Por ahora, nos estamos enfocando en los casos de uso de dos de los elementos más comunes del lenguaje de plantillas. En mi propio trabajo, básicamente solo uso las etiquetas for y if de forma regular, aunque la docena o más de otras etiquetas proporcionadas tienen sus propios casos de uso, que le animo a revisar en la referencia de la plantilla.

Antes de llegar a las etiquetas, quiero hacer una nota sobre la sintaxis. La etiqueta {% foo %} significa que "foo" es una función u otra capacidad del propio sistema de plantillas, mientras que la etiqueta {{ bar }} significa que "bar" es una variable que se pasa a la plantilla específica.

Para bucles

En el index.html restante, la sección de código más grande por varios cientos de líneas es la tabla. En lugar de esta tabla codificada, podemos generar la tabla dinámicamente desde la base de datos. python manage.py loaddata employee_fixture.json del paso de configuración. Ese comando usó un archivo JSON, llamado Django Fixture, para cargar los 57 registros de empleados en la base de datos de la aplicación. Usamos la vista en views.py para pasar estos datos a la plantilla:

 from django.shortcuts import render from .models import Employee def index(request): return render(request, "index.html", {"employees": Employee.objects.all()})

El tercer argumento posicional para render es un diccionario de datos que se pone a disposición de la plantilla. Usamos estos datos y la etiqueta for para construir la tabla. Incluso en la plantilla original de la que adapté esta página web, la tabla de empleados estaba codificada. Nuestro nuevo enfoque corta cientos de líneas de filas repetitivas de tablas codificadas. index.html ahora contiene:

 {% for employee in employees %} <trv <td>{{ employee.name }}</td> <td>{{ employee.position }}</td> <td>{{ employee.office }}</td> <td>{{ employee.age }}</td> vtd>{{ employee.start_date }}</td> <td>${{ employee.salary }}</td> </tr> {% endfor %}

La mayor ventaja es que esto simplifica enormemente el proceso de actualización de la tabla. En lugar de que un desarrollador edite manualmente el HTML para reflejar un aumento de salario o una nueva contratación, y luego impulsar ese cambio a producción, cualquier administrador puede usar el panel de administración para realizar actualizaciones en tiempo real (https://127.0.0.1/admin, use las credenciales que creó con python manage.py createsuperuser para acceder). Este es un beneficio de usar Django con este motor de renderizado en lugar de usarlo solo en un generador de sitios estáticos u otro enfoque de plantillas.

Si más

La etiqueta if es una etiqueta increíblemente poderosa que le permite evaluar expresiones dentro de la plantilla y ajustar el HTML en consecuencia. Líneas como {% if 1 == 2 %} son perfectamente válidas, aunque un poco inútiles, ya que evalúan siempre el mismo resultado. Donde brilla la etiqueta if es cuando interactúa con los datos pasados ​​a la plantilla por la vista. Considere el siguiente ejemplo de sidebar.html :

 <div class="sb-sidenav-footer"> <div class="small"> Logged in as: </div> {% if user.is_authenticated %} {{ user.username }} {% else %} Start Bootstrap {% endif %} </div>

Tenga en cuenta que todo el objeto de usuario se pasa a la plantilla de forma predeterminada, sin que especifiquemos nada en la vista para que eso suceda. Esto nos permite acceder al estado de autenticación del usuario (o la ausencia del mismo), el nombre de usuario y otras características, incluido el seguimiento de relaciones de clave externa para acceder a los datos almacenados en un perfil de usuario u otro modelo conectado, todo desde el archivo HTML.

Es posible que le preocupe que este nivel de acceso pueda presentar riesgos de seguridad. Sin embargo, recuerde que estas plantillas son para un marco de renderizado del lado del servidor. Después de construir la página, las etiquetas se consumen y se reemplazan con HTML puro. Por lo tanto, si una declaración if introduce datos en una página bajo ciertas condiciones, pero los datos no se utilizan en una instancia determinada, entonces esos datos no se enviarán al cliente en absoluto, ya que la declaración if se evalúa del lado del servidor. Esto significa que una plantilla construida correctamente es un método muy seguro para agregar datos confidenciales a las páginas sin que esos datos abandonen el servidor a menos que sea necesario. Dicho esto, el uso de plantillas de Django no elimina la necesidad de comunicar información confidencial de manera segura y cifrada, simplemente significa que las comprobaciones de seguridad como user.is_authenticated pueden realizarse de forma segura en el HTML a medida que se procesa en el lado del servidor.

Esta característica tiene una serie de otros casos de uso. Por ejemplo, en la página de inicio general de un producto, es posible que desee ocultar los botones "registrarse" e "iniciar sesión" y reemplazarlos con un botón "cerrar sesión" para los usuarios que iniciaron sesión. Otro uso común es mostrar y ocultar mensajes de éxito o error para operaciones como el envío de formularios. Tenga en cuenta que, por lo general, no ocultaría toda la página si el usuario no ha iniciado sesión. Una mejor manera de cambiar toda la página web en función del estado de autenticación del usuario es manejarla en la función adecuada en views.py .

Filtración

Parte del trabajo de la vista es formatear los datos adecuadamente para la página. Para lograr esto, tenemos una poderosa extensión para etiquetas: filtros. Hay muchos filtros disponibles en Django para realizar acciones como justificar texto, formatear fechas y agregar números. Básicamente, puede pensar en un filtro como una función que se aplica a la variable en una etiqueta. Por ejemplo, queremos que nuestros números de salario digan “$1,200,000” en lugar de “1200000”. Usaremos un filtro para hacer el trabajo en index.html :

 <td>${{ employee.salary|intcomma }}</td>

El personaje de la pipa | es el filtro que aplica el comando intcomma a la variable employee.salary . El carácter “$” no proviene de la plantilla, para un elemento como ese que aparece cada vez, es más fácil pegarlo fuera de la etiqueta.

Tenga en cuenta que intcomma requiere que incluyamos {% load humanize %} en la parte superior de nuestro index.html y 'django.contrib.humanize', en nuestras INSTALLED_APPS en settings.py . Esto se hace por usted en la aplicación de muestra provista.

Conclusión

La representación del lado del servidor con el motor Jinja2 proporciona herramientas clave para crear un código front-end limpio, adaptable y con capacidad de respuesta. La separación de páginas en archivos permite componentes DRY con una composición flexible. Las etiquetas proporcionan capacidades fundamentales para mostrar datos pasados ​​desde la base de datos por funciones de visualización. Bien hecho, este enfoque puede aumentar la velocidad, las capacidades de SEO, la seguridad y la facilidad de uso del sitio, y es un aspecto central de la programación en Django y marcos similares.

Si aún no lo ha hecho, consulte la aplicación de muestra e intente agregar sus propias etiquetas y filtros usando la lista completa.

Django Highlights es una serie que presenta conceptos importantes del desarrollo web en Django. Cada artículo está escrito como una guía independiente de una faceta del desarrollo de Django con la intención de ayudar a los desarrolladores y diseñadores front-end a alcanzar una comprensión más profunda de "la otra mitad" del código base. Estos artículos están construidos principalmente para ayudarlo a comprender la teoría y la convención, pero contienen algunos ejemplos de código, que están escritos en Django 3.0.

Piezas anteriores de la serie:

  • Aspectos destacados de Django: Modelos de usuario y autenticación (Parte 1)
  • Aspectos destacados de Django: modelos, administración y aprovechamiento de la base de datos relacional (parte 3)
  • Aspectos destacados de Django: disputa de activos estáticos y archivos multimedia (Parte 4)