Renderizar Templates En Django

Fecha de publicaci贸n: 6 Diciembre 2020
Tiempo de lectura: 5 min.
Premium: False
N煤mero de visitas: 1113


C贸mo se ha mencionado anteriormente, Django es un Framework Web que utiliza el patron de dise帽o MTV, por su siglas al ingles: Model, Template, Views. Pudiendo as铆 separar nuestra l贸gica de negocios con la presentaci贸n de los datos.

Si bien es cierto, el c贸mo almacenar, obtener y procesar la informaci贸n es pieza clave para nuestros proyectos, el c贸mo ser谩 visualizada tambi茅n lo es. Vaya, me atrevo a decir que, en la mayor铆a de los casos, el definir c贸mo el usuario podr谩 visualizar la informaci贸n jugar谩 un papel clave en la estrategia para obtener y procesar los datos. 馃構

Y es por esta raz贸n que, en esta ocasi贸n, me gustar铆a abord谩ramos el tema de templates en Django. Explicaremos las diferentes formas de obtener y renderizar templates, adem谩s de los tipos de usos que podemos darles.

Es sin duda un tema bastante interesante, y al cual sin duda le podr谩s sacar mucho provecho. Bien, sin m谩s introducci贸n, comencemos.

Templates

Comencemos con lo b谩sico, 驴Qu茅 es un template? Podemos definir un template como el archivo a trav茅s del cual el usuario podr谩 visualizar la informaci贸n que solicita. Com煤nmente asociamos los templates para archivos .html y, si bien es cierto, estamos en lo correcto, en Django no es el 煤nico tipo de archivo que podemos utilizar. De igual forma podemos presentar la informaci贸n en archivos .XML, .YAML, .JSON etc.. Esto gracias al fabuloso motor de Template que posee el Framework. 馃コ

Aqu铆 un peque帽o ejemplo para pintar el username de los 煤ltimos usuarios obtenidos.

<div class="col-6">
    <h5>脷ltimos tokens generados.</h5>
    <ul>
        {% for user in last_users %}
            <li> {{ user.username }} </li>
            {% if user.active %}
                <p>Usuario activo</p>
            {% endif %}
        {% endfor %}
    </ul>
</div>

C贸mo podemos observar, dentro de los template podemos hacer uso de sentencias Python, como lo pueden ser ciclos y/o condicionales. Esto es algo que nos viene de maravillas para poder crea p谩ginas web din谩micas, p谩ginas la cuales se creen en cuesti贸n a las necesidades del usuario, pudiendo pintar diferentes bloques de informaci贸n dependiendo cu谩l sea el caso.

Y ahora, si eres nuevo en Django, quiz谩s te estes preguntando 驴C贸mo puedo utilizar los templates para pintar la informaci贸n que deseo? La respuesta puede ser algo extensa, ya que existen m煤ltiples formas de hacerlo, pero comencemos con la m谩s sencilla, con la funci贸n render.

Funci贸n render

La funci贸n render, tal y como su nombre nos indica, nos permite renderizar un template. As铆 de sencillo. La funci贸n nos ser谩 de mucha 煤tilidad cuando deseamos responder a la petici贸n de un cliente mediante alguna p谩gina web, o 驴por qu茅 no? tambi茅n podemos utilizar para crear nuestros propios correo electr贸nicos. 鉁

La funci贸n podemos encontrarla dentro del m贸dulo shortcuts.

from django.shortcuts import render

Esta funci贸n recibe como argumento, de forma obligatoria, 3 valores. La petici贸n per se, el template a renderizar y un contexto. El contexto no ser谩 m谩s que un diccionario cuyas llaves podr谩n ser utilizadas dentro del template.

Aqu铆 un ejemplo.

def premium(request, slug):
    article = get_object_or_404(Article, slug=slug)

    return render(request, 'articles/premium.html', {
        'article': article,
    })

Para este ejemplo enviamos el objeto Article al nuestro template, pudiendo as铆 utilizarlo para crear una p谩gina web din谩mica, accediendo y condicionando, o iterando, sobre cada uno de sus atributos o m茅todos. 馃

<h1>{{ article.title }}</h1>
<p>
    {{ article.content }}
</p>

Ahora, es importante mencionar que, por default, Django buscar谩 el template dentro del folder template de nuestras aplicaciones.

Por ejemplo, para nuestra aplicaci贸n articles el path ser铆a el siguiente: articles/templates/articles/premium.html

Un poco confuso 驴No? bueno para m铆 lo fue al principio. Tener que crear el folder template para cada una de nuestras aplicaciones puede resultar en algo tedioso, necesario, pero tedioso. 馃槪 Afortunadamente hay forma de solucionarlo.

Y ahora 驴Qu茅 pasa si no me encuentro trabajando con ning煤n tipo de aplicaci贸n o simplemente quiero especificar otro folder en d贸nde deseo almacenar mis templates? Bueno, en esos casos Django nos ofrece una peque帽a alternativa. En nuestro archivo settings.py debemos modificar la constante TEMPLATES.

Dentro del listado, para la llave DIRS, vamos a colocar el nombre de nuestro folder en d贸nde pretendemos almacenar nuestros templates.

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': ['templates'],
        'APP_DIRS': True,
        'OPTIONS': {
         ...
        },
    },
]

Al nosotros hacer esto, siempre que renderizemos un template, Django primero buscar谩 dicho archivo en el folder (o folders) que hayamos indicados en el archivo de configuraci贸n, en caso el folder no se encuentre all铆, se har谩 la b煤squeda dentro de la aplicaci贸n pertinente, y en caso de tampoco encontrarlo, el error TemplateDoesNotExist ser谩 lanzado.

Nota: La funci贸n render retornar un objeto de tipo HTTPResponse, por lo que es posible almacenarlo en una variable para posteriormente manipularlo. Algo que ya estaremos viendo en otra entrega. 馃コ

response = render(request, 'subscriptions/subscription.html', context)
response.set_cookie('coupon_code', coupon.code)

return response

Obtener template

Otra forma de poder obtener y renderizar un template, es mediante la funci贸n get_template. Esta funci贸n recibe c贸mo argumento la ruta del template a utilizar, y retorna un objeto de tipo template. Utilizando el m茅todo render del objeto, seremos capaces de renderizar nuestro template.

Aqu铆 un ejemplo para crear un correo electr贸nico a partir de un template con etiquetas html.

from django.template.loader import get_template
from django.core.mail import EmailMultiAlternatives

template = get_template('users/mails')
content = template.render(
    {
        'user': user
    }
)

msg = EmailMultiAlternatives(
    subject, 
    'PyWombat',
    settings.FROM_EMAIL,
    [user.email],
)


msg.attach_alternative(content, 'text/html')

Vistas basadas en clases.

Si bien la funci贸n render podemos utilizarla pr谩cticamente en cualquier parte del proyecto, es com煤nmente implementada para las vistas en funciones; tal y como pudimos observar en el ejemplo anterior. Pero, 驴Qu茅 pasa si nos encontramos implementado vistas basadas en clase? Pff, pues all铆 las cosas cambiar radicalmente. O bueno, no tanto as铆, pero s铆 cambian. 馃槄

Ver谩s, las vistas basadas en clase tienen como objetivo agilizar el proceso de desarrollo, implementando ciertas convenciones para ello. Veamos un ejemplo.

class ArticleDetailView(DetailView):
    model = Article

En este caso, mi clase al tener por nombre ArticleDetailView y heredar de la clase DetailView, se buscar谩 por default el template: articles/article_detail.html dentro de la aplicaci贸n articles. La convenci贸n ser铆a la siguiente: nuestro modelo / el nombre de nuestra clase (con nomenclatura snake case) + .html. Esto puede funcionar para muchos, para m铆 no.

Afortunadamente Django nos da la facilidad de poder definir de forma muy puntual con qu茅 template queremos trabajar. Esto gracias al tributo template_name y el m茅todo get_template_names. Vamos uno a uno.

Utilizando el atributo template_name indicaremos expl铆citamente el template a renderizar, evitando as铆 utilizar el default de la clase. 馃悪

class ArticleDetailView(DetailView):
    model = Article
    template_name = 'articles/detailt.html'

De forma personal me hace mucho m谩s sentido utilizar el template detail.html que se almacena en folder article que la ruta: articles/article_detail.html (Una doble redundancia).

Esto funcionar谩 perfectamente siempre que deseemos utilizar el mismo template para todas las peticiones. Sin embargo, en caso el template a utilizar depende completamente de ciertas condiciones deberemos apoyarnos del m茅todo get_template_names.

El m茅todo get_template_names retorna un listado de templates a renderizar. El primer template ser谩 el que se utilizar谩 馃槺

Ejemplo.

def get_template_names(self):
    if not self.request.user.is_anonymous:
        return ['articles/detail.html']
    else:
        return ['articles/subscription.html']

En este caso el template a renderizar depende completamente en si el usuarios de encuentra autenticado o no. C贸mo podemos observar dependiendo cual sea el caso se har谩 uso de uno u otro template.

Por supuesto, esta es una condici贸n bastante sencilla, no dudo que t煤 podr谩s sacarle mucho m谩s provecho. 馃構

Ojo, es importante mencionar que el renderizar un template u otro no tiene absolutamente nada que ver con re dirigir al usuario. Recuerda que los templates nos permitir谩n mostrar de diferentes formas.

Conclusi贸n

Listo, en esta entrega aprendimos un par de cosas acerca de los templates, principalmente el c贸mo poder utilizarlos. Si bien estas no son las 煤nicas formas de hacerlo, de hecho hay un par m谩s, que implican, ya sea el uso de nuevas clases o inclusive middlewares, si consider贸 son las m谩s comunes, y con las cuales sin dudas estaremos trabajando en nuestro d铆a a d铆a como desarrollador Django. 馃嵒

M谩s Tips y Ejercicios 馃悕

Adquiere una subscripci贸n PyWombat por tan solo $3 USD. al mes.

Conoce los beneficios de ser usuario premium:
Niveles desbloqueados: Ten accesos a todos los niveles de ejercicios. 馃敁
Nuevo l铆mite: Incrementa tu l铆mite de ejercicios por semana. 馃殌
Contenido 煤nico: Recibe semanalmente recursos exclusivos de Python (Videos, Art铆culos y Capitulos del libro PyWombat, comienza como desarrollador Python. 馃悕