Antes de empezar quiero confesar que no soy ningún especialista en diseño web (como se puede apreciar en este blog), siempre me ha parecido mas interesante la programación, por lo que intento conseguir los mejores resultados dedicando el mínimo tiempo y esfuerzo posible a HTML y CSS. Para ello uso frameworks como Bootstrap o Foundation en la mayoría de mis proyectos, y los adapto usando el sistema de plantillas de Django.

El proceso es sencillo y en este tutorial describo como hacerlo para Bootstrap, aunque es válido para cualquier otro framework.

Base

El sistema de plantillas de Django es jerárquico de manera que unas plantillas extienden o heredan de otras, todo empieza con base.html la plantilla a partir de la cual se crean las demás, esta contiene la estructura mínima HTML5 así como los elementos necesario para el funcionamiento del framework Bootstrap (CSS y librarias JS).

{% load staticfiles %}

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">

        <title>{% block title %}Dominio | Titulo pagina {% endblock %}</title>
        <meta name="description" content="{% block description %}{% endblock %}"/>

        <link href="{% static "bootstrap/css/bootstrap.min.css" %}" rel="stylesheet">
        <link href="{% static "bootstrap/css/local.min.css" %}" rel="stylesheet">

        <!--[if lt IE 9]>
            <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
            <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
        <![endif]-->
        {% block head %}
        {% endblock %}
    </head>

    <body>
        {% include "navbar.html" %}

        <div class="container">
            {% block content %}
            {% endblock %}
        </div>

        {% include "footer.html" %}

        <!-- All that javascript -->
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
        <script src="{% static "bootstrap/js/bootstrap.min.js" %}"></script>

        {% block scripts %}
        {% endblock %}
    </body>
</html>

base.html define 6 bloques que pueden ser modificados/extendidos por otras plantillas:

  • title: Título de la página, con un valor por defecto.
  • description: Descripción de la página.
  • head: Bloque para añadir cualquier tag extra a la cabecera, por ejemplo CSS específico de una página.
  • content: Bloque principal donde se añadirá todo el contenido desde otras plantillas.
  • scripts: Para añadir librerías y código javascript extra.

Las barras de navegación y el pie de página se han añadido usando include por claridad, pero pueden incluirse directamente en base.html. Un archivo navbar.html puede ser algo similar a esto:

<nav class="navbar navbar-inverse navbar-fixed-top">
    <div class="container">
        <div class="navbar-header">
            <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="/">Project name</a>
        </div>
        <div id="navbar" class="collapse navbar-collapse">
            <ul class="nav navbar-nav">
                <li class="active"><a href="/">Home</a></li>
                <li><a href="{% url 'about' %}">About</a></li>
                <li><a href="{% url 'contact' %}">Contact</a></li>
            </ul>
        </div><!--/.nav-collapse -->
    </div>
</nav>

Si en tu diseño la barra de navegación o el pie de página no son fijos, en su lugar deja sendos bloques vacios para añadirlos posteriormente, también puedes añadir cualquier otro bloque que creas que vas a necesitar.

Estructura

El siguiente paso es extender base.html y crear plantillas que plasman las distintas estructuras que usarán las páginas de la aplicación, para ello usa el framework elegido y añade bloques extensibles en cada uno de los elementos.

Por ejemplo para recrear un diseño simple de dos columnas como el de la figura inferior, solo es necesario añadir los bloques main-content y sidebar puesto que la cabecera y pie de página ya están presentes.


Diseño

Eso se puede crear fácilmente usando Bootstrap:

{% extends "base.html" %}

{% block content %}

    <div class="row">
        <div class="col-md-8 col-sm-12">
            {% block main-content %}{% endblock %}
        </div>
        <div class="col-md-4 hidden-sm">
            {% block sidebar %}{% endblock %}
        </div>
    </div>

{% endblock %}

En este caso he usado la clase hidden-sm para que la barra lateral desaparezca, y col-sm-12 para que la de contenido ocupe toda la ventana cuando el viewport del navegador sea menor de 750px.

Es importante que estas plantillas sean versátiles, por lo que deben contener el mínimo número de elementos necesarios para crear el diseño/estructura, de esta manera que puedan ser reusadas en múltiples páginas. Piensa que es fácil extender plantillas y añadir elementos mas adelante, en cambio es imposible eliminar los elementos existentes.

Includes

Las plantillas con la estructura son extendidas para crear las plantillas finales usadas para renderizar en las vistas, por ejemplo una página de contacto:

{% extends "base-2col.html" %}

{% block title %}Información de contacto{% endblock %}

{% block main-content %}
    <h1>Contacto</h1>
    <hr>
    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer nec odio. Praesent libero. Sed cursus ante dapibus diam. Sed nisi. Nulla quis sem at nibh elementum imperdiet. Duis sagittis ipsum. Praesent mauris. Fusce nec tellus sed augue semper porta. Mauris massa. Vestibulum lacinia arcu eget nulla. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Curabitur sodales ligula in libero. Sed dignissim lacinia nunc. </p>

    <p>...</p>
{% endblock %}

{% block scripts %}
    <script src="{% static "js/bling.js" %}"></script>
{% endblock %}

Aquí comienza a verse la flexibilidad que ofrece el sistema de plantillas de Django y con que facilidad permite crear nuevas páginas. Aún así queda un problema por solucionar ya que en algunos casos te vas a encontrar varias plantillas con código duplicado, algo que va contra el principio DRY. Por suerte el código se puede refactorizar usando el tag include.

Include es junto a extends uno de los mecanismos con los que se puede reutilizar código entre plantillas. Permite cargar una plantilla dentro de otra, renderizarla usando el contexto actual, e incluir el resultado en su lugar. Por ejemplo en un blog donde más de una vista muestra listas de posts (últimos posts, mas visitados, ...), tendrás varias plantillas con el mismo bucle renderizandolas. Con include se puede crear una plantilla que contiene el bucle, y luego incluirla cada vez que sea necesario monstrar listas de posts:

{% for p in posts %}
    <div class="blog-post">
        <h2 class="blog-post-title">{{p.title}}</h2>
        <p class="blog-post-meta">{{p.date}} by {{p.poster.name}}</p>
        <hr>
        {{p.content}}
    </div>
{% endfor %}

Y luego en la plantilla que tiene que mostrar la lista de posts:

{% extends "base-2col.html" %}

{% block title %}Últimos posts{% endblock %}

{% block main-content %}
    <h1>Ultimos posts</h1>
    {% include "post-list.html" with posts=last-posts %}
{% endblock %}

En este caso la variable de contexto last-posts contiene la lista de los posts que ha de mostrar.

Formularios

Casi todos los frameworks requieren añadir algún tag alrededor de los formularios para poder aplicar estilos, si ese formato no es el generado por django será necesario editar manualmente las plantillas. Por suerte si estas usando Bootstrap existe el app django-bootstrap-form que permite generar formularios usando su formato. Su funcionamiento es muy sencillo:

{% load bootstrap %}

<form role="form">
    <legend>Form Title</legend>
    {% csrf_token %}
    {{ form|bootstrap }}
    <div class="form-group">
      <button type="submit" class="btn btn-primary">Submit</button>
    </div>
</form>

Simplemente hay que cargar los tags al inicio de la plantilla y usar bootstrap o bootstrap_horizontal junto al tag del formulario.

Rendimiento

Por último ten en cuenta que cuantas más veces uses extends e include, más bloques tengan tus plantillas, y mas variables uses más lento será su renderizado. Esto tiene múltiples soluciones, desde cambiar a un sistema de plantillas más rápido como Jinja, a activar el sistema de cacheado de Django , o minimizar el uso de extends uniendo todas las plantillas. Puedes encontrar múltiples artículos sobre el tema:

Yo te recomiendo que lo ignores hasta que se convierta en un problema real, la optimización prematura según dicen es la raíz de todos los males.


comments powered by Disqus