【问题标题】:Django: How can I get a block from a template?Django:如何从模板中获取块?
【发布时间】:2011-02-10 20:16:30
【问题描述】:

假设我的模板中包含{% block subject %}my subject{% endblock %} 之类的内容,并且我使用tmpl = loader.get_template('mytemplate.html') 加载此模板,我该如何提取“我的主题”?

【问题讨论】:

  • 纯粹出于好奇,你到底为什么要这么做?
  • @Jack:电子邮件!我已经有了电子邮件模板,但我也想把主题放在那里。
  • 出于同样的原因,我偶然发现了这个问题,想将我的电子邮件主题、html 和普通版本放在一个模板中。有人为你制作了一个 PIP 包(django-render-block)。

标签: python django django-templates


【解决方案1】:
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())

这对我有用,使用 Django 1.1.1

【讨论】:

    【解决方案2】:

    当您的模板扩展基础时,Camilo 的解决方案不起作用。我已经对其进行了一些修改以(希望)解决该问题:

    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)
    

    我真的不确定这是否是递归迭代所有节点的正确方法......但它在我有限的情况下有效。

    【讨论】:

    • 其实...刚刚找到了一个更好的解决方案。现在将电子邮件模板直接存储在数据库中。使 em 更易于编辑,可以将 HTML 和文本版本存储在一个条目中(而不是 2 个文件),我也可以为主题添加一个字段。
    • 我已经把这个 sn-p 带到了下一个级别,并使它更广泛地与递归模板一起工作 - github.com/bradwhittington/django-templated-email/blob/… 如果你在继承中使用 {{block.super}} 它会破坏/丢失信息模板。很高兴接受修复,这将使它更完整
    【解决方案3】:

    我希望这可以制作一个包含标签,它只获取相关模板的一部分。我在这里分享它,以防其他人出于同样的原因想要它。

    用法:{% 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)
    

    【讨论】:

      【解决方案4】:

      Django 1.8以来,建议的答案不起作用:

      在 Django 1.8 中更改:get_template() 返回依赖于后端的 模板而不是 django.template.Template。

      新的 django.template.backends.django.Template 不可迭代,所以 for 循环会报错:

      “模板”对象不可迭代。

      使用 Django 模板系统的解决方案(基于@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())
      

      【讨论】:

        猜你喜欢
        • 2011-11-11
        • 2018-09-23
        • 2014-07-13
        • 1970-01-01
        • 2012-12-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多