2010-11-29 35 views
2

Peut-on compiler ou rétablir une partie de l'AST Jinja2?Compiler la sous-section de Jinja2 AST

Par exemple, est-il possible d'appeler une fonction ou une méthode de jinja2.environment ou jinja2.compiler.generate ou un équivalent sur une liste de nœuds extraits d'un modèle?

Par exemple, étant donné un modèle y.html:

avant-tag 
{% xyz %} 
tag content {{ 3 + 5 }} 
{% endxyz %} 
apres-tag 

et une extension y.py:

# -*- coding: utf-8 -*- 
from jinja2 import nodes, Environment, FileSystemLoader 
from jinja2.ext import Extension 

class YExtension(Extension): 
    tags = set(['y']) 

    def __init__(self, environment): 
     super(YExtension, self).__init__(environment) 

    def parse(self, parser): 
     tag = parser.stream.next() 
     body = parser.parse_statements(['name:endy'], drop_needle=True) 
     return nodes.Const("<!-- slurping: %s -->" % str(body)) 

env = Environment(
    loader  = FileSystemLoader('.'), 
    extensions = [YExtension], 
    ) 

print env.get_template('x.html').render() 

Exécution python y.py résultats dans la sortie attendue de:

avant-tag 
<!-- slurping: [Output(nodes=[TemplateData(data=u'\n tag-content '), 
    Add(left=Const(value=3), right=Const(value=5)), 
    TemplateData(data=u'\n ')])] --> 
sous-tag 

Dans le parse méthode, comment peut-on soit:

  1. compiler body en unicode (c.-à-d. tag-content 8); ou, en variante,
  2. de rétablir body à sa source d'origine (c'est-à-dire tag-content {{ 3 + 5 }}).

En arrière-plan, cette question a trait à deux questions précédentes:

  1. Jinja2 compile extension after includes; et
  2. Insert javascript at top of including file in Jinja 2

Merci pour la lecture.

Brian

Répondre

1

à unicode est Compiler pas encore possible dans la méthode parse() puisque vous n'avez pas le contexte disponible à ce moment-là. Vous pouvez le contourner bien sûr, mais ce ne serait probablement pas la meilleure façon d'y aller.

Notez que l'étape parse() est normalement exécutée une seule fois sur un fichier html, après quoi il utilisera le bytecode analysé pour rendre le modèle. Les résultats de l'étape d'analyse peuvent être rendus compte tenu d'un environnement.

Vous n'avez tout simplement pas le contexte disponible là-bas, et d'obtenir le contexte là-dedans ... assez difficile;)

Pour obtenir cependant la source d'origine ... pas beaucoup plus facile sans le piratage, mais le piratage est pas trop mal;)

class YExtension(Extension): 
    tags = set(['y']) 

    def preprocess(self, source, name, filename=None): 
     # insert some code here that replaces '{% xyz %}foo bar{% endxyz %}' 
     # with something like: '{% xyz %}foo bar{% raw %}foo bar{% endraw %}{% endxyz %}' 
     return source 

Après cela, vous pouvez lire le texte comme value du nœud {% raw %}. Assurez-vous de le jeter après cela ou il apparaîtra dans votre modèle.

+0

Merci WoLpH. Je pense que cela répond à ma question. La seule question résiduelle, je pense, est de savoir s'il existe un moyen de rendre les résultats extraits dans un environnement. –

+0

@Brian M. Hunt: ce n'est pas un problème puisque vous pouvez rendre n'importe quelle chaîne dans les deux sens. Vous pouvez utiliser 'Environment.from_string()' ou 'Template (nodes)' avec tout ce que vous auriez normalement renvoyé. – Wolph

+0

Oh, c'est vrai! Désolé, je n'étais pas clair ...La seule question résiduelle, je pense, est de savoir s'il existe un moyen de rendre les ** noeuds ** extraits (et non le texte) dans un environnement donné. –