Django - 如何从模板中获取{%block%}标记的内容 [英] Django - how to get the contents of a {% block %} tag from a template

查看:147
本文介绍了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)
>>>块[0]
<块节点:another_block。内容:[<文本节点:'\\\
这是真的很酷'><块节点:sub_block。内容:[<文本节点:'\\\
I\'是子块。\\\
\t'>]><文本节点:'\\\
'>]>
>>>那就是当我意识到这不是很有趣的时候。

你看,一个块的内容包含在 block.nodelist ,而不是纯文本。如果我有一个模板:

  {%extendsbase.html%} 

{% block some_block%}
某些值
{%endblock%}

{%block other_block%}
其他值
{%sub_block%}子块值{%endblock%}
{%endblock%}

我想能够执行此操作:

 >>> get_block_source('other_block')
'\\\
Other Value\\\
{%sub_block%}子块值{%endblock%} \\\
'
>>> get_block_source('sub_block')
'子块值'

如果Django的内部不提供足够的资源找到一种方法来做到这一点,我也可以使用正则表达式/一系列的正则表达式,但是我看不到如何可以使用正则表达式,因为你可以嵌套 {%block ... 标签

解决方案

我创建的解决方案: / p>

  import re 


BLOCK_RE = re.compile(r'{%\s * block\s *(\w +)\s *%}')
NAMED_BLOCK_RE = r'{%% \s * block\s *%s\s * %%}'#接受字符串格式
ENDBLOCK_RE = re.compile(r'{%\s * endblock\s *(?: \w + \s *)?%}')


def get_block_source(template_source,block_name):

给定模板的源代码和定义的块标签的名称,
返回块标签内的源。

#查找打开的块给定的名称
match = re.search(NAMED_BLOCK_RE%(block_name,),template_source)
如果match为None:
raise ValueError(u'Template block {n} not found'.format (n = block_name))
end = inner_start = start = match.end()
end_width = 0
while True:
#设置``end``当前结束外面的前一个结束块
end + = end_width
#查找下一个结束块
match = re.search(ENDBLOCK_RE,template_source [end:])
#设置`` end``到下一个结束块内
end + = match.start()
#获取结束块的宽度,以防另一个迭代
end_width = match.end( ) - match.start()
#搜索任何以前找到的打开块之间的任何打开的块,
#和当前的``end``
嵌套= re.search(BLOCK_RE,template_source [inner_start:end])
如果嵌套是无:
#没有任何东西nd,所以我们有正确的结束块
break
else:
#发现嵌套的开放块,所以设置我们的嵌套搜索光标只是
#通过内部打开的块,找到并继续迭代
inner_start + = nested.end()
#返回我们的``start``和最后``end``位置之间的值
return template_source [start:end ]


I got this far:

>>> 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.

You see, the contents of a block are contained in block.nodelist, as opposed to just plain text. If I have a template:

{% extends "base.html" %}

{% block some_block %}
Some value
{% endblock %}

{% block other_block %}
Other Value
    {% sub_block %}Sub block value{% endblock %}
{% endblock %}

I want to be able to do this:

>>> get_block_source('other_block')
'\nOther Value\n    {% sub_block %}Sub block value{% endblock %}\n'
>>> get_block_source('sub_block')
'Sub block value'

If Django's internals don't provide enough resourced to find a way to do this, I'm OK with using a regex / series of regex as well, but I don't see how it'd be possible with regex alone, given that you can have nested {% block... tags.

解决方案

The solution I created:

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]

这篇关于Django - 如何从模板中获取{%block%}标记的内容的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆