Flask

Flask

Tutorial Flask: Inclusión de archivos estáticos en Jinja

Flask: Aprende a estructurar y gestionar eficientemente recursos estáticos, integrando CSS, JS e imágenes en tus proyectos web.

Aprende Flask GRATIS y certifícate

Estructura de carpetas para recursos estáticos

En Flask, la organización de la estructura de carpetas es crucial para gestionar eficientemente los recursos estáticos. Por defecto, Flask busca estos recursos en una carpeta llamada static ubicada en el directorio raíz de la aplicación.

Una estructura básica de un proyecto Flask sería:

mi_proyecto/
│
├── app.py
├── static/
│   ├── css/
│   ├── js/
│   └── images/
└── templates/

En este esquema, la carpeta static contiene todos los archivos estáticos como hojas de estilo (CSS), archivos JavaScript e imágenes. Es una buena práctica organizar estos archivos en subcarpetas dentro de static para mantener un orden lógico. Por ejemplo, almacenar los archivos CSS en la subcarpeta css, los scripts en js y las imágenes en images.

El archivo principal de la aplicación, comúnmente llamado app.py, se sitúa en el directorio raíz junto a las carpetas static y templates. Esta disposición permite que Flask detecte automáticamente dónde buscar los archivos estáticos y las plantillas Jinja.

Cuando se trabaja con blueprints, cada módulo puede tener sus propias carpetas static y templates. La estructura del proyecto podría adaptarse de la siguiente manera:

mi_proyecto/
│
├── app.py
├── mod_usuario/
│   ├── __init__.py
│   ├── views.py
│   ├── static/
│   └── templates/
└── mod_admin/
    ├── __init__.py
    ├── views.py
    ├── static/
    └── templates/

Con esta organización, los recursos estáticos y las plantillas están segmentados por módulo, lo que facilita la modularización y el mantenimiento en aplicaciones de mayor envergadura. Cada módulo gestiona sus propios recursos, lo que contribuye a una estructura más limpia y escalable.

Es esencial mantener una nomenclatura consistente y una estructura clara para simplificar el desarrollo y permitir que otros desarrolladores entiendan fácilmente la disposición del proyecto. Una correcta organización de las carpetas asegura que Flask pueda servir los recursos estáticos sin inconvenientes.

Uso de la función url_for con archivos estáticos

En Flask, la función url_for es esencial para generar URLs dinámicas y precisas en las plantillas Jinja, especialmente al referenciar archivos estáticos como hojas de estilo, scripts o imágenes. Utilizar url_for garantiza que las rutas se actualicen automáticamente si cambian las configuraciones de la aplicación, evitando enlaces rotos.

Al incluir una hoja de estilo en una plantilla, se emplea url_for de la siguiente manera:

<link rel="stylesheet" href="{{ url_for('static', filename='css/estilos.css') }}">

En este ejemplo, url_for construye la URL completa para el archivo estilos.css ubicado en static/css. Esto es preferible a escribir una ruta estática como /static/css/estilos.css, ya que url_for se adapta si el prefijo de la URL cambia en diferentes entornos o si se configura una ruta estática personalizada.

Para incluir archivos JavaScript, se sigue una lógica similar:

<script src="{{ url_for('static', filename='js/app.js') }}"></script>

Las imágenes también se incorporan utilizando url_for:

<img src="{{ url_for('static', filename='images/logo.png') }}" alt="Logo de la empresa">

Utilizar url_for ofrece varias ventajas:

  • Flexibilidad en la configuración: Si la aplicación se despliega bajo un subdirectorio o se cambia el static_url_path, las rutas generadas con url_for se actualizan automáticamente.
  • Mantenibilidad: Evita la necesidad de actualizar manualmente las rutas en las plantillas si cambian las ubicaciones de los archivos o la estructura de directorios.
  • Integración con Blueprints: Cuando se utilizan Blueprints, cada uno puede tener su propia carpeta static, y url_for gestiona correctamente las rutas.

Por ejemplo, con un Blueprint llamado admin:

<link rel="stylesheet" href="{{ url_for('admin.static', filename='css/admin.css') }}">

Aquí, url_for busca el archivo admin.css dentro de la carpeta static específica del Blueprint admin.

Es importante recordar que el primer argumento de url_for es el nombre del endpoint. Para archivos estáticos globales, se utiliza 'static' por defecto. El parámetro filename indica la ruta relativa al directorio static.

Además, url_for puede manejar parámetros adicionales, lo que permite la generación de URLs con cache busting añadiendo un token único, aunque en Flask esto no es nativo y requeriría una extensión o función personalizada.

Una práctica común para mejorar el rendimiento es servir los archivos estáticos directamente desde el servidor web en producción, como Nginx o Apache, y utilizar url_for para mantener la coherencia en las rutas durante el desarrollo y pruebas.

La incorporación de CSS, JavaScript e imágenes en las plantillas Jinja de Flask es esencial para crear aplicaciones web interactivas y atractivas. Una vez organizados los recursos estáticos en su estructura de carpetas correspondiente, es fundamental integrarlos correctamente en las plantillas para que el navegador los cargue adecuadamente.

Para incluir una hoja de estilo CSS, se utiliza la etiqueta <link> dentro del <head> de la plantilla HTML, haciendo referencia al archivo mediante la función url_for:

<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <title>Mi Aplicación Flask</title>
    <link rel="stylesheet" href="{{ url_for('static', filename='css/estilos.css') }}">
</head>
<body>
    <!-- Contenido de la página -->
</body>
</html>

En este ejemplo, el archivo estilos.css se encuentra en la ruta static/css/. La función url_for genera la URL correcta al recurso estático, asegurando su accesibilidad sin importar la configuración de la aplicación.

Para agregar archivos JavaScript, se emplea la etiqueta <script> justo antes del cierre de la etiqueta </body>:

    <!-- Contenido de la página -->
    <script src="{{ url_for('static', filename='js/funciones.js') }}"></script>
</body>
</html>

Colocar los scripts al final del documento mejora el rendimiento, ya que permite que el contenido principal se cargue primero. Si se utilizan múltiples archivos JavaScript, es importante mantener un orden lógico para evitar conflictos.

La inclusión de imágenes en el contenido se realiza con la etiqueta <img>, también utilizando url_for:

<img src="{{ url_for('static', filename='images/logo.png') }}" alt="Logo de la empresa">

Siempre es recomendable proporcionar un texto alternativo en el atributo alt para mejorar la accesibilidad y el SEO del sitio.

Si se utilizan fuentes personalizadas o íconos, como Font Awesome, se pueden agregar de manera similar:

<link rel="stylesheet" href="{{ url_for('static', filename='fonts/fontawesome/css/all.min.css') }}">

Para estilos o scripts específicos de una página, se puede utilizar la herencia de plantillas de Jinja y definir bloques que permitan agregar recursos adicionales:

<!-- En layout.html -->
<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <title>{% block titulo %}{% endblock %}</title>
    <link rel="stylesheet" href="{{ url_for('static', filename='css/estilos.css') }}">
    {% block estilos_extra %}{% endblock %}
</head>
<body>
    {% block contenido %}{% endblock %}
    <script src="{{ url_for('static', filename='js/funciones.js') }}"></script>
    {% block scripts_extra %}{% endblock %}
</body>
</html>

En una plantilla que extienda de layout.html, se pueden añadir estilos o scripts adicionales:

<!-- En pagina.html -->
{% extends "layout.html" %}

{% block titulo %}Página Específica{% endblock %}

{% block estilos_extra %}
    <link rel="stylesheet" href="{{ url_for('static', filename='css/pagina.css') }}">
{% endblock %}

{% block contenido %}
    <h1>Página Específica</h1>
    <p>Contenido de la página.</p>
    <img src="{{ url_for('static', filename='images/pagina.jpg') }}" alt="Imagen de la página">
{% endblock %}

{% block scripts_extra %}
    <script src="{{ url_for('static', filename='js/pagina.js') }}"></script>
{% endblock %}

Esta técnica facilita la organización y reutilización de código, permitiendo una gestión más eficiente de los recursos en proyectos de mayor envergadura.

Cuando se trabaja con archivos CSS que contienen referencias a imágenes u otras fuentes, es importante tener en cuenta las rutas relativas. Por ejemplo, en un archivo estilos.css ubicado en static/css/:

/* En static/css/estilos.css */
.background {
    background-image: url('../images/fondo.jpg');
}

La ruta ../images/fondo.jpg es relativa al directorio del archivo CSS y apunta correctamente a static/images/fondo.jpg.

Para optimizar la carga de recursos, es aconsejable:

  • Minificar archivos CSS y JavaScript para reducir su tamaño.
  • Utilizar compresión de imágenes sin perder calidad notable.
  • Implementar caché en el navegador para recursos estáticos.

Integrar librerías externas como Bootstrap puede hacerse a través de un CDN o descargando los archivos y almacenándolos localmente:

<!-- Uso de CDN -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css">

<!-- Uso de archivos locales -->
<link rel="stylesheet" href="{{ url_for('static', filename='css/bootstrap.min.css') }}">

El uso de archivos locales puede ser beneficioso para el rendimiento y el control sobre la versión utilizada.

Al incorporar JavaScript, especialmente cuando se depende de bibliotecas como jQuery o Bootstrap JS, es crucial mantener el orden correcto:

    <!-- Scripts necesarios -->
    <script src="{{ url_for('static', filename='js/jquery.min.js') }}"></script>
    <script src="{{ url_for('static', filename='js/bootstrap.bundle.min.js') }}"></script>
    <script src="{{ url_for('static', filename='js/funciones.js') }}"></script>
</body>

Esto asegura que las dependencias estén disponibles cuando se ejecuten los scripts personalizados.

La gestión adecuada de los recursos estáticos mejora significativamente la experiencia del usuario, al proporcionar tiempos de carga más rápidos y una interfaz más receptiva. Además, seguir estas prácticas facilita el mantenimiento y la escalabilidad de la aplicación a medida que crece en complejidad.

Organización y optimización de recursos

La organización eficiente y la optimización de los recursos estáticos son fundamentales para mejorar el rendimiento y la escalabilidad de las aplicaciones Flask. Una correcta gestión de estos recursos reduce los tiempos de carga y proporciona una mejor experiencia al usuario.

Para optimizar los recursos estáticos, es recomendable utilizar herramientas de minificación que reduzcan el tamaño de los archivos CSS y JavaScript eliminando espacios en blanco y comentarios innecesarios. Por ejemplo, se pueden integrar procesos de build con Webpack o Gulp para automatizar la minificación y concatenación de archivos.

La implementación de una estrategia de cache busting es esencial para asegurarse de que los clientes reciben siempre la versión más reciente de los recursos. Una técnica común es añadir un hash o número de versión al nombre del archivo:

<link rel="stylesheet" href="{{ url_for('static', filename='css/estilos.min.css?v=1.0.0') }}">

Otra opción es automatizar este proceso generando nombres de archivo únicos basados en el contenido, utilizando herramientas como Flask-Assets, que integra el manejo de activos estáticos y facilita tareas como la compilación y minificación:

from flask_assets import Environment, Bundle

assets = Environment(app)
css_bundle = Bundle('css/estilos.css', filters='cssmin', output='gen/estilos.min.css')
js_bundle = Bundle('js/app.js', 'js/utilidades.js', filters='jsmin', output='gen/app.min.js')

assets.register('css_all', css_bundle)
assets.register('js_all', js_bundle)

En las plantillas Jinja, se pueden referenciar los bundles registrados:

<link rel="stylesheet" href="{{ url_for('static', filename=assets['css_all'].output) }}">
<script src="{{ url_for('static', filename=assets['js_all'].output) }}"></script>

El uso de Content Delivery Networks (CDNs) para servir bibliotecas populares como jQuery o Bootstrap puede mejorar la velocidad de carga al aprovechar la caché del navegador si el usuario ya visitó otros sitios que utilizan los mismos CDNs. Sin embargo, para recursos propios, es preferible servirlos desde el propio servidor o una CDN privada para mantener el control.

La compresión GZIP o Brotli de los archivos estáticos reduce notablemente el tamaño de las transferencias. En entornos de producción, configurar el servidor web para que sirva archivos comprimidos mejora el rendimiento sin necesidad de modificaciones en Flask.

Para imágenes, es conveniente utilizar formatos modernos como WebP o AVIF que ofrecen mejor compresión sin perder calidad. Además, aplicar técnicas de carga diferida o lazy loading en las imágenes que están fuera de la vista inicial mejora la velocidad percibida por el usuario.

Implementar headers de caché apropiados en las respuestas HTTP indica al navegador cuánto tiempo puede almacenar en caché cada recurso estático. En Flask, se pueden personalizar las respuestas de archivos estáticos utilizando la función send_from_directory con parámetros adicionales:

from flask import send_from_directory, make_response

@app.route('/static/<path:filename>')
def custom_static(filename):
    response = make_response(send_from_directory('static', filename))
    response.headers['Cache-Control'] = 'public, max-age=31536000'
    return response

La organización de los recursos dentro del proyecto debe facilitar el mantenimiento y la escalabilidad. Clasificar los archivos por funcionalidad o módulo, y utilizar convenciones de nomenclatura coherentes, ayuda a los desarrolladores a ubicarlos y actualizarlos con facilidad.

En aplicaciones grandes, considerar el uso de preprocesadores como SASS o LESS para CSS, y TypeScript o Babel para JavaScript, permite escribir código más robusto y modular. Estos requieren un proceso de compilación, que puede integrarse en el flujo de trabajo mediante herramientas como Flask-Assets o scripts de automatización externos.

Para el despliegue en producción, es recomendable servir los recursos estáticos a través de un servidor web como Nginx o Apache, configurados para manejar eficientemente las peticiones de archivos estáticos y liberar a Flask de esa carga. Esto mejora la capacidad de respuesta de la aplicación al enfocarse exclusivamente en la lógica de negocio.

Para seguir leyendo hazte Plus

¿Ya eres Plus? Accede a la app

20 % DE DESCUENTO

Plan mensual

19.00 /mes

15.20 € /mes

Precio normal mensual: 19 €
58 % DE DESCUENTO

Plan anual

10.00 /mes

8.00 € /mes

Ahorras 132 € al año
Precio normal anual: 120 €
Aprende Flask GRATIS online

Todas las lecciones de Flask

Accede a todas las lecciones de Flask y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.

Accede GRATIS a Flask y certifícate

En esta lección

Objetivos de aprendizaje de esta lección

  • Comprender la organización básica de carpetas en un proyecto Flask para recursos estáticos.
  • Implementar la función url_for correctamente en plantillas Jinja.
  • Diferenciar entre recursos estáticos globales y específicos de Blueprints.
  • Optimizar la carga de CSS, JS e imágenes para mejorar el rendimiento.
  • Aplicar cache busting y minificación para recursos optimizados.
  • Integrar CDN para bibliotecas externas manteniendo control local.