/ / Запит шаблону для змінних, які йому потрібні? - django, змінні, django-шаблони

Запитувати шаблон для потрібних змінних? - django, змінні, django-шаблони

Я хотів би спробувати екземпляр шаблонуз файлу (імовірно, використовуючи django.template.loader.get_template (ім'я_файлу)), а потім визначити набір змінних, які повинні бути визначені в будь-якому контексті, який він передано.

Я думав, що в об'єкті шаблону буде метод, але, здається, не існує.

Я читаю документи, і найближчий, який я знайшов, це:

http://docs.djangoproject.com/en/1.0/topics/templates/#using-the-built-in-reference

що пропонує перейти до інтерфейсу адміністратора, щоб побачити всі змінні, пов'язані з даним представленням.

Я не хочу пройти інтерфейс адміністратора, тому що я хочу це зробити програмним шляхом - я намагаюся написати тести.

Я використовую версію Django (1, 0, 2, "фінальний", 0)

Оновлено:

Я спробував відповідь Синак і виявив, що (ззаміна «filter_expression.token by filter_expression.var», щоб отримати фактичне ім'я змінної без тегів і т. д.) він повернув змінні, які визначаються локально у шаблоні, але не працюють для змінних, визначених батьком, що він продовжується

Так, наприклад, припустимо, у мене є шаблони у двох файлах:

toyparent.html:

{%block base_results%}
Django is {{adjective}}
{%endblock base_results%}

toychild.html:

{% extends "toyparent.html" %}

{%block base_results%}
{{block.super}}
I {{verb}} it.
{%endblock base_results %}

І я завантажую шаблон дитини:

>>> toy=django.template.loader.get_template("toychild.html")

Це правильно відображається:

>>> toy.render(django.template.Context(dict(adjective="cool",verb="heart")))
u"n    nDjango is coolnn    I heart it.nn"

Але я не можу отримати дві змінні від нього:

>>> v=toy.nodelist.get_nodes_by_type(VariableNode)
>>> for k in v: print k.filter_expression.var
...
block.super
verb

Відповіді:

20 за відповідь № 1

Ви можете візуально перевірити шаблон і спостерігати наявність будь-яких об'єктів "Variable Node" у цьому шаблоні "nodelist:

>>> 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 змінні повернулися з таких тестів? Не знаю!!

У будь-якому випадку, це інформація, яку ви хотіли,але я не думаю, що це практичне рішення. Я наполягаю на тому, що все ще є, можливо, кращий спосіб. Можливо варто поглянути на те, що ви намагаєтеся вирішити, і подивитеся, чи є інший підхід, який ви можете зробити.