Django - как получить содержимое тега {% block %} из шаблона
Я получил это далеко:
>>> some_template = get_template_from_string(
... load_template_source(
... 'some_template.html',
... settings.TEMPLATE_DIRS))
...
>>> blocks = some_template.nodelist.get_nodes_by_type(BlockNode)
>>> blocks[0]
<Block Node: another_block. Contents: [<Text Node: '\nThis one is really cool'>, <Block Node: sub_block. Contents: [<Text Node: '\nI\'m a sub-block.\n\t'>]>, <Text Node: '\n'>]>
>>> # Right there is when I realized this wasn't going to be fun.
Вы видите, содержимое блока содержится в block.nodelist
, а не просто текст. Если у меня есть шаблон:
{% extends "base.html" %}
{% block some_block %}
Some value
{% endblock %}
{% block other_block %}
Other Value
{% sub_block %}Sub block value{% endblock %}
{% endblock %}
Я хочу быть в состоянии сделать это:
>>> get_block_source('other_block')
'\nOther Value\n {% sub_block %}Sub block value{% endblock %}\n'
>>> get_block_source('sub_block')
'Sub block value'
Если внутренности Django не предоставляют достаточно ресурсов, чтобы найти способ сделать это, я в порядке и с использованием регулярного выражения / серии регулярных выражений, но я не понимаю, как это было бы возможно с помощью одного регулярного выражения, учитывая, что ты можешь быть вложенным {% block...
теги.
2 ответа
Решение, которое я создал:
import re
BLOCK_RE = re.compile(r'{%\s*block\s*(\w+)\s*%}')
NAMED_BLOCK_RE = r'{%%\s*block\s*%s\s*%%}' # Accepts string formatting
ENDBLOCK_RE = re.compile(r'{%\s*endblock\s*(?:\w+\s*)?%}')
def get_block_source(template_source, block_name):
"""
Given a template's source code, and the name of a defined block tag,
returns the source inside the block tag.
"""
# Find the open block for the given name
match = re.search(NAMED_BLOCK_RE % (block_name,), template_source)
if match is None:
raise ValueError(u'Template block {n} not found'.format(n=block_name))
end = inner_start = start = match.end()
end_width = 0
while True:
# Set ``end`` current end to just out side the previous end block
end += end_width
# Find the next end block
match = re.search(ENDBLOCK_RE, template_source[end:])
# Set ``end`` to just inside the next end block
end += match.start()
# Get the width of the end block, in case of another iteration
end_width = match.end() - match.start()
# Search for any open blocks between any previously found open blocks,
# and the current ``end``
nested = re.search(BLOCK_RE, template_source[inner_start:end])
if nested is None:
# Nothing found, so we have the correct end block
break
else:
# Nested open block found, so set our nested search cursor to just
# past the inner open block that was found, and continue iteration
inner_start += nested.end()
# Return the value between our ``start`` and final ``end`` locations
return template_source[start:end]
Это кажется, что вы трудолюбивый против зерна Джанго. Поместите содержимое во включаемый файл, затем {% include %}
это в вашем блоке, а также читать файл напрямую. Если бы вы могли рассказать нам больше о том, чего вы пытаетесь достичь, возможно, есть лучший способ сделать это.