Genera contenido dinámico desde plantillas


Esta parte de la explicación del código Guestbook de Python muestra cómo utilizar las plantillas de Jinja para generar contenido web dinámico.

Esta página forma parte de un instructivo de varias páginas. Si deseas comenzar desde el principio y ver las instrucciones para la configuración, consulta Cómo crear un libro de visitas.

Resulta difícil mantener un archivo HTML incorporado en el código. Es mejor usar un sistema de plantillas, en el que el archivo HTML se guarda en un archivo separado con una sintaxis especial que indica dónde aparecen los datos de la aplicación. Hay muchos sistemas de plantillas para Python, como: EZT, Cheetah, ClearSilver, Quixote, Django, y Jinja2, entre otros. Puedes utilizar el motor de plantilla que prefieras y combinarlo con el código de la aplicación.

Para tu comodidad, App Engine incluye los motores de plantillas de Django y Jinja2.

Cómo utilizar las plantillas de Jinja2

El archivo app.yaml enumera la versión más reciente de jinja2 como una biblioteca obligatoria. Las aplicaciones de producción deben usar un número de versión real en lugar de version: latest.

libraries:
- name: webapp2
  version: latest
- name: jinja2
  version: latest

La app importa jinja2 y crea un objeto jinja2.Environment.

import os
import urllib

from google.appengine.api import users
from google.appengine.ext import ndb

import jinja2
import webapp2

JINJA_ENVIRONMENT = jinja2.Environment(
    loader=jinja2.FileSystemLoader(os.path.dirname(__file__)),
    extensions=['jinja2.ext.autoescape'],
    autoescape=True)

El método get para el controlador de solicitudes MainPage forma un diccionario de pares clave-valor y lo pasa a template.render.

class MainPage(webapp2.RequestHandler):

    def get(self):
        guestbook_name = self.request.get('guestbook_name',
                                          DEFAULT_GUESTBOOK_NAME)
        greetings_query = Greeting.query(
            ancestor=guestbook_key(guestbook_name)).order(-Greeting.date)
        greetings = greetings_query.fetch(10)

        user = users.get_current_user()
        if user:
            url = users.create_logout_url(self.request.uri)
            url_linktext = 'Logout'
        else:
            url = users.create_login_url(self.request.uri)
            url_linktext = 'Login'

        template_values = {
            'user': user,
            'greetings': greetings,
            'guestbook_name': urllib.quote_plus(guestbook_name),
            'url': url,
            'url_linktext': url_linktext,
        }

        template = JINJA_ENVIRONMENT.get_template('index.html')
        self.response.write(template.render(template_values))

La página se procesa de acuerdo con la plantilla index.html, que recibe el diccionario como entrada.

{% for greeting in greetings %}
<div class="row">
  {% if greeting.author %}
    <b>{{ greeting.author.email }}
      {% if user and user.user_id() == greeting.author.identity %}
        (You)
      {% endif %}
    </b> wrote:
  {% else %}
    An anonymous person wrote:
  {% endif %}
  <blockquote>{{ greeting.content }}</blockquote>
</div>
{% endfor %}

El método JINJA_ENVIRONMENT.get_template(name) toma el nombre de un archivo de plantilla y muestra un objeto de plantilla. La llamada template.render(template_values) toma un diccionario de valores y muestra el texto procesado. La plantilla utiliza la sintaxis de Jinja2 para acceder y, luego, iterar los valores, y puede hacer referencia a las propiedades de esos valores.