2010-04-21 20 views
6

Supongamos que mi plantilla tiene algo así como {% block subject %}my subject{% endblock %} y cargo esta plantilla con tmpl = loader.get_template('mytemplate.html'), ¿cómo puedo extraer "mi asunto"?Django: ¿Cómo puedo obtener un bloque de una plantilla?

+1

Sólo por curiosidad, ¿por qué querrías? –

+3

@Jack: ¡correos electrónicos! Ya tengo plantillas de correo electrónico, pero también quiero poner el tema allí. – mpen

+1

Me encontré con esta pregunta por la misma razón, con el deseo de poner mi tema de correo electrónico, html y versión simple en una plantilla. Alguien ha creado un paquete PIP que hace esto por usted (django-render-block). –

Respuesta

6

de Camilo no funciona cuando la plantilla se extiende una base. He modificado un poco para (esperemos) solucionar ese problema:

from django.template import Context 
from django.template.loader import get_template 
from django.template.loader_tags import BlockNode, ExtendsNode 

def _get_node(template, context=Context(), name='subject'): 
    for node in template: 
     if isinstance(node, BlockNode) and node.name == name: 
      return node.render(context) 
     elif isinstance(node, ExtendsNode): 
      return _get_node(node.nodelist, context, name) 
    raise Exception("Node '%s' could not be found in template." % name) 

Realmente no estoy seguro de si este es el camino correcto para recorrer de forma recursiva sobre todos los nodos ... pero funciona en mi limitado caso.

+0

En realidad ... acaba de encontrar una solución aún mejor. Almacenar las plantillas de correo electrónico directamente en el DB ahora. Hace que sea más fácil de editar, puede almacenar versiones HTML y de texto en una entrada (en lugar de 2 archivos) y también puedo agregar un campo para el tema. – mpen

+4

He llevado este fragmento al siguiente nivel y lo he hecho funcionar más ampliamente con plantillas recursivas: https://github.com/bradwhittington/django-templated-email/blob/867ef61693d02a39ca902a30e66d5dd7dd941cda/templated_email/utils.py se rompe/pierde información si usa {{block.super}} en plantillas heredadas. Acepta con gusto las correcciones que lo harán más completo – Darb

5
from django.template import Context 
from django.template.loader import get_template 
from django.template.loader_tags import BlockNode 

t = get_template('template.html') 
for node in t: 
    if isinstance(node, BlockNode) and node.name == 'subject': 
     print node.render(Context()) 

Esto funcionó para mí, usando una solución de Django 1.1.1

3

Quería que se creara una etiqueta de inclusión que obtenga solo una sección de la plantilla en cuestión. Lo estoy compartiendo aquí por si acaso alguien más lo quisiera por el mismo motivo.

de uso: {% include_block "template.html" "block_name" %}

@register.tag 
def include_block(parser, token): 
    try: 
     tag_name, include_file, block_name = token.split_contents() 
    except ValueError: 
     raise template.TemplateSyntaxError("%r tag requires a two arguments" % (token.contents.split()[0])) 

    #pass vars with stripped quotes 
    return IncludeBlockNode(include_file.replace('"', ''), block_name.replace('"', '')) 

class IncludeBlockNode(template.Node): 
    def __init__(self, include_file, block_name): 
     self.include_file = include_file 
     self.block_name = block_name 

    def _get_node(self, template, context, name): 
     ''' 
     taken originally from 
     http://stackoverflow.com/questions/2687173/django-how-can-i-get-a-block-from-a-template 
     ''' 
     for node in template: 
      if isinstance(node, BlockNode) and node.name == name: 
       return node.nodelist.render(context) 
      elif isinstance(node, ExtendsNode): 
       return self._get_node(node.nodelist, context, name) 

     raise Exception("Node '%s' could not be found in template." % name) 

    def render(self, context): 
     t = get_template(self.include_file) 
     return self._get_node(t, context, self.block_name) 
5

Las respuestas propuestas no trabajo desde Django 1.8:

Changed in Django 1.8: get_template() returns a backend-dependent Template instead of a django.template.Template.

Los nuevos django.template.backends .django.Template no es iterable, por lo que un bucle da el error:

'Template' object is not iterable.

a solutio n para los que utilizan el sistema de plantillas de Django (basado en la respuesta CamiloDíazRepka @):

from django.template import Context 
from django.template.loader import get_template 
from django.template.loader_tags import BlockNode 

t = get_template('template.html') 
for node in t.template: 
    if isinstance(node, BlockNode) and node.name == 'subject': 
     print node.render(Context()) 
Cuestiones relacionadas