/ / Zapytanie o szablon dla potrzebnych zmiennych? - django, zmienne, szablony django

Zapytanie o szablon dla potrzebnych zmiennych? - django, zmienne, szablony django

Chciałbym móc utworzyć instancję szablonuz pliku (prawdopodobnie za pomocą django.template.loader.get_template (filename)), a następnie określić zestaw zmiennych, które powinny być zdefiniowane w jakimkolwiek kontekście, w którym jest przekazywany.

Sądziłem, że na obiekcie szablonu znajdzie się metoda, ale wydaje się, że nie jest.

Czytałem dokumenty i najbliżej znalazłem to:

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

co sugeruje przejście do interfejsu administratora, aby zobaczyć wszystkie zmienne związane z danym widokiem.

Nie chcę przechodzić przez interfejs administratora, ponieważ chcę to zrobić programowo - próbuję pisać testy.

Używam wersji Django (1, 0, 2, "final", 0)

Zaktualizowano:

Wypróbowałem odpowiedź synacka i odkryłem, że (zzastąpienie wyrażenia filter_expression.token przez filter_expression.var, aby uzyskać rzeczywistą nazwę zmiennej bez znaczników itd.) zwróciło zmienne zdefiniowane lokalnie w szablonie, ale nie działało dla zmiennych zdefiniowanych w obiekcie macierzystym, rozszerza się.

Załóżmy na przykład, że mam szablony w dwóch plikach:

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 %}

I ładuję szablon podrzędny:

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

Zapewnia to prawidłowe:

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

Ale nie mogę pobrać z niego dwóch zmiennych:

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

Odpowiedzi:

20 dla odpowiedzi nr 1

Jesteś w stanie wizualnie sprawdzić szablon i obserwować obecność dowolnych obiektów "Zmiennego Węzła" w nodelistyce tego szablonu:

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

Są tego typu VariableNode, która jest klasą, którą można bezpośrednio importować w celu użycia w porównaniach. Każdy Node instancja ma get_nodes_by_type() metoda, która może zostać wywołana przeciwko węzłowi, który zwraca wszystkie węzły tego typu dla szablonu. Przykład:

>>> from django.template import VariableNode
>>> varnodes = t.nodelist.get_nodes_by_type(VariableNode)
>>> varnodes
[<Variable Node: adjective>, <Variable Node: verb>]

Masz teraz listę zmiennych do szablonu. Będzie to musiało zostać zrobione o krok dalej, aby wyodrębnić rzeczywistą nazwę każdej zmiennej bez wykonywania głupich sztuczek z cięciem strunowym na ich repr nazwy.

Sama nazwa zmiennej jest przechowywana w filter_expression.token dla każdego VariableNode:

>>> varnodes[0].filter_expression.token
u"adjective"

Tak więc proste zrozumienie listy powoduje, że dostajemy wszystkie nazwy zmiennych dla szablonu:

>>> template_vars = [x.filter_expression.token for x in varnodes]
>>> template_vars
[u"adjective", u"verb"]

Więc nie jest to najprostsze rozwiązanie, ale jeśli jest lepszy sposób, nie wiem o tym.

Premia: Funkcja!!

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]

Ok, to wcale nie jest takie skomplikowane!

Kontynuacja Edycja: pobieranie zmiennych z szablonów nadrzędnych

(Ta kontynuacja wykorzystuje informacje z zaktualizowanego pytania).

To właśnie w tym przypadku robi się skomplikowane, ponieważ nodelistą szablonu zabawki jest singiel ExtendsNode (w tym przypadku).

>>> toy.nodelist
[<ExtendsNode: extends "mysite/toyparent.html">]

Wyobrażam sobie, że w większych szablonach może istnieć wiele ExtendsNode obiekty. W każdym razie, jeśli przejrzysz ExtendsNodei wyodrębnij z niego szablon nadrzędny, możesz traktować rodzica tak samo jak mój oryginalny przykład:

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

I jest twoje adjective zmienna wyodrębniona z szablonu nadrzędnego. Aby wykonać test przeciwko ExtendsNode możesz zaimportować klasę z 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">]

Tak, możesz zrobić kilka testów przeciwko szablonom na obecność ExtendsNode i przejdź wstecz do szablonu nadrzędnego i pojedynczo pobierz te nazwy zmiennych. Jednak zaczyna to wyglądać jak puszka robaków.

Na przykład, jeśli chcesz to zrobić:

>>> toy.nodelist.get_nodes_by_type((ExtendsNode, VariableNode))
[<ExtendsNode: extends "mysite/toyparent.html">, <Variable Node: block.super>, <Variable Node: verb>]

Teraz masz ExtendsNode i VariableNode obiekty i po prostu zaczynają być mylące. Co wtedy robimy? Czy próbujemy zignorować jakiekolwiek block zmienne zwrócone z takich testów? Nie wiem!!

W każdym razie jest to informacja, której szukasz,ale nie sądzę, że jest to praktyczne rozwiązanie, twierdzę, że prawdopodobnie jest jeszcze lepszy sposób, warto zastanowić się nad tym, co próbujesz rozwiązać i zobaczyć, czy istnieje inne podejście, które możesz zastosować.