2010-04-21 16 views
6

Supponiamo che il mio modello abbia qualcosa come {% block subject %}my subject{% endblock %} e carico questo modello con tmpl = loader.get_template('mytemplate.html'), come posso estrarre "il mio soggetto"?Django: Come posso ottenere un blocco da un modello?

+1

Solo per pura curiosità, perché mai vorresti? –

+3

@Jack: email! Dispongo già di modelli di email, ma voglio mettere il soggetto anche lì. – mpen

+1

Mi sono imbattuto in questa domanda per lo stesso motivo, volendo mettere la mia email oggetto, html e versione semplice in un modello. Qualcuno ha creato un pacchetto PIP che fa questo per te (django-render-block). –

risposta

6

soluzione Django di Camilo non funziona quando il modello si estende una base. Ho modificato un po 'per (si spera) risolvere questo 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) 

Io non sono davvero sicuro se questo è il modo giusto per iterare ricorsivamente su tutti i nodi ... ma funziona nella mia limitata Astuccio.

+0

In realtà ... ho appena trovato una soluzione ancora migliore. Memorizza i modelli di email direttamente nel DB ora. Rende più facile la modifica, in grado di memorizzare sia la versione HTML sia la versione di testo in un'unica voce (anziché in 2 file) e posso aggiungere anche un campo per l'oggetto. – mpen

+4

Ho preso questo snippet a The Next Level e l'ho reso più ampio con i modelli ricorsivi: https://github.com/bradwhittington/django-templated-email/blob/867ef61693d02a39ca902a30e66d5dd7dd941cda/templated_email/utils.py si rompe/perde informazioni se usi {{block.super}} in modelli ereditati. Accetto volentieri le correzioni che lo renderanno più 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()) 

questo ha funzionato per me, utilizzando 1.1.1

3

Volevo che questo facesse un tag include che ottiene solo una sezione del modello in questione. Lo sto condividendo qui nel caso in cui qualcun altro lo volesse per lo stesso motivo.

utilizzo: {% 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

Le risposte proposte non funzionano dal Django 1.8:

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

I nuovi django.template.backends .django.Template non è iterabile, quindi un ciclo for dà l'errore:

'Template' object is not iterable.

a solutio n per chi usa il sistema di template Django (basato sulla risposta @ 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()) 
Problemi correlati