Вы можете визуально проверить шаблон и наблюдать наличие любых объектов «Переменного узла» в списке узлов этого шаблона:
>>> from django.template import Template, Context
>>> t = Template("Django is {{ adjective }} and I {{ verb }} it.")
>>> t.nodelist
[<Text Node: 'Django is '>, <Variable Node: adjective>, <Text Node: ' and I '>, <Variable Node: verb>, <Text Node: ' it.'>]
Они относятся к типу VariableNode
, который является классом, который можно напрямую импортировать для использования в сравнениях. Любой экземпляр Node
имеет метод get_nodes_by_type()
, который можно вызывать для списка узлов, который возвращает все узлы этого типа для шаблона. Пример:
>>> from django.template import VariableNode
>>> varnodes = t.nodelist.get_nodes_by_type(VariableNode)
>>> varnodes
[<Variable Node: adjective>, <Variable Node: verb>]
Итак, теперь у вас есть список переменных для шаблона. Для этого потребуется сделать еще один шаг, чтобы извлечь действительное имя каждой переменной, не выполняя глупых трюков с разрезанием строк на их repr
именах.
Само имя переменной хранится в filter_expression.token
для каждого VariableNode
:
>>> varnodes[0].filter_expression.token
u'adjective'
И вот простое понимание списка дает нам все имена переменных для шаблона:
>>> template_vars = [x.filter_expression.token for x in varnodes]
>>> template_vars
[u'adjective', u'verb']
Итак, не самое простое решение, но если есть лучший способ, я не знаю об этом.
Бонус: Функция !!
from django.template import VariableNode
def get_template_vars(t):
varnodes = t.nodelist.get_nodes_by_type(VariableNode)
return [x.filter_expression.token for x in varnodes]
Хорошо, все не так сложно!
Последующее редактирование: получение переменных из родительских шаблонов
(Это продолжение использует информацию из обновленного вопроса).
Вот где он действительно становится сложным, потому что список узлов игрушечного шаблона - это один ExtendsNode
(в данном случае).
>>> toy.nodelist
[<ExtendsNode: extends "mysite/toyparent.html">]
Я бы предположил, что в больших шаблонах может быть несколько ExtendsNode
объектов. В любом случае, если вы осмотрите ExtendsNode
и извлечете из него родительский шаблон, вы сможете обращаться с родительским шаблоном так же, как в моем исходном примере:
>>> enode = toy.nodelist[0]
>>> enode.parent_name
u'mysite/toyparent.html'
>>> parent = enode.get_parent(enode.parent_name)
>>> parent
<django.template.Template object at 0x101c43790>
>>> parent.nodelist.get_nodes_by_type(VariableNode)
[<Variable Node: adjective>]
И ваша adjective
переменная извлечена из родительского шаблона. Чтобы выполнить тест по ExtendsNode
, вы можете импортировать класс из django.template.loader_tags
:
>>> from django.template.loader_tags import ExtendsNode
>>> ext = toy.nodelist.get_nodes_by_type(ExtendsNode)
>>> ext
[<ExtendsNode: extends "mysite/toyparent.html">]
Итак, вы могли бы провести несколько тестов с шаблонами на наличие ExtendsNode
и вернуться назад к родительскому шаблону и по отдельности получить эти имена переменных. Тем не менее, это начинает казаться банкой червей.
Например, если вы должны были сделать это:
>>> toy.nodelist.get_nodes_by_type((ExtendsNode, VariableNode))
[<ExtendsNode: extends "mysite/toyparent.html">, <Variable Node: block.super>, <Variable Node: verb>]
Теперь у вас есть объекты ExtendsNode
и VariableNode
, и это только начинает сбивать с толку. Что мы будем делать тогда? Пытаемся ли мы игнорировать переменные block
, полученные из таких тестов? Я не знаю !!
В любом случае, это та информация, которую вы хотели, но я не думаю, что это практическое решение. Я настаиваю на том, что есть еще лучший способ. Возможно, стоит разобраться в том, что вы пытаетесь решить, и посмотреть, есть ли другой подход, который вы можете использовать.