Reputation: 282865
Suppose my template has in it something like {% block subject %}my subject{% endblock %}
and I load this template with tmpl = loader.get_template('mytemplate.html')
, how can I extract "my subject"?
Upvotes: 10
Views: 3944
Reputation: 86
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())
Upvotes: 5
Reputation: 1509
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)
Upvotes: 3
Reputation: 282865
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.
Upvotes: 8
Reputation: 4815
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
Upvotes: 5