开发者

Django: How can I get a block from a template?

开发者 https://www.devze.com 2022-12-28 05:28 出处:网络
Suppose my template has in it something like {% block subject %}my subject{% endblock %} and I load this templa开发者_如何学JAVAte with tmpl = loader.get_template(\'mytemplate.html\'), how can I extra

Suppose my template has in it something like {% block subject %}my subject{% endblock %} and I load this templa开发者_如何学JAVAte with tmpl = loader.get_template('mytemplate.html'), how can I extract "my subject"?


Camilo's solution doesn't work when your template extends a base. I've modified it a bit to (hopefully) fix that problem:

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)

I'm really not sure if this is the right way to recursively iterate over all the nodes... but it works in my limited case.


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())

This worked for me, using Django 1.1.1


The proposed answers don't work since Django 1.8:

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

The new django.template.backends.django.Template isn't iterable, so a for loop gives the error:

'Template' object is not iterable.

A solution for those who use Django template system (based on @CamiloDíazRepka answer):

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())


I wanted this to make an include tag that gets only a section of the template in question. I'm sharing it here just in case someone else wanted it for the same reason.

Usage: {% 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)
0

精彩评论

暂无评论...
验证码 换一张
取 消