Джанго: Как я могу получить блок из шаблона? - PullRequest
7 голосов
/ 22 апреля 2010

Предположим, что в моем шаблоне есть что-то вроде {% block subject %}my subject{% endblock %}, и я загружаю этот шаблон с помощью tmpl = loader.get_template('mytemplate.html'), как мне извлечь "мой предмет"?

Ответы [ 4 ]

6 голосов
/ 08 июля 2010

Решение 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)

Я действительно не уверен, что это правильный способ рекурсивной итерации по всем узлам ... но это работает в моем ограниченном случае.

5 голосов
/ 14 апреля 2015

Предлагаемые ответы не работают с Django 1.8 :

Изменено в Django 1.8: get_template () возвращает бэкэнд-зависимый Шаблон вместо django.template.Template.

Новый django.template.backends.django.Template не повторяется, поэтому цикл for выдает ошибку:

Объект 'Template' не повторяется.

Решение для тех, кто использует систему шаблонов 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())
5 голосов
/ 22 апреля 2010
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

3 голосов
/ 10 декабря 2011

Я хотел сделать тег включения, который получает только часть рассматриваемого шаблона. Я делюсь этим здесь на случай, если кто-то еще захочет этого по той же причине.

Использование: {% 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
        /2200948/dzhango-kak-ya-mogu-poluchit-blok-iz-shablona
        '''
        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)
...