2014-04-19 7 views
5

Ist es möglich, eine Jinja2-Erweiterung zu schreiben, die während des Renderns auf den Vorlagenkontext zugreifen kann? Ich möchte eine Erweiterung schreiben, die auf eine Kontextvariable zugreift und einige Daten basierend auf dieser Variable ausgibt. Ich konnte nicht genug Informationen darüber finden, wie man eine solche Erweiterung schreibt.Jinja-Erweiterung, die Zugriff auf Kontext hat

Im Moment habe ich dies:

class CsrfExtension(jinja2.ext.Extension): 
    r""" Adds a {% csrf %} tag to Jinja. """ 

    tags = set(['csrf']) 
    template = '<input type="hidden" name="csrfmiddlewaretoken" value="%s">' 

    def parse(self, parser): 
     token = next(parser.stream) 
     lineno = token.lineno 
     return self.call_method('_render_csrf', lineno=lineno) 

    def _render_csrf(self, value, name, *args, **kwargs): 
     csrf_token = somehow_get_variable('csrf_token') 
     return jinja2.Markup(self.template % csrf_token) 

Aber in foo.jinja

<!DOCTYPE html> 
<html> 
    <body> 
     <h1>This is a Test</h1> 
     {% csrf %} 
    </body> 
</html> 

I

bekommen
SyntaxError at/
invalid syntax (foo.jinja, line 7) 

Ich dachte, ich bekäme Nameerror seit somehow_get_variable() nicht ist definiert. Ich muss a) wissen, wie man die Variable aus dem aktuellen Kontext holt, und b) wie man die Extension korrekt schreibt.

Auch warum Linie 7? Die {% csrf %}-Tag auf der Leitung 5. Selbst wenn ich foo.jinja trimmen nur eine Zeile mit dem {% csrf %} Tag darin haben, heißt es Linie 7.

Antwort

7

es gefunden. Scheint so, als ob Jinja Python-Code aus dem Jinja-AST (?) Generiert und diese Konvertierung fehlgeschlagen ist, deshalb verursachte der SyntaxError. jinja2.nodes.ContextReference() kann verwendet werden, um den Render-Kontext zu erhalten.

class CsrfExtension(jinja2.ext.Extension): 
    r""" Adds a {% csrf %} tag to Jinja. """ 

    tags = set(['csrf', 'csrf_token']) 
    template = u'<input type="hidden" name="csrfmiddlewaretoken" value="%s">' 

    def parse(self, parser): 
     lineno = next(parser.stream).lineno 
     ctx_ref = jinja2.nodes.ContextReference() 
     node = self.call_method('_render_csrf', [ctx_ref], lineno=lineno) 
     return jinja2.nodes.CallBlock(node, [], [], [], lineno=lineno) 

    def _render_csrf(self, context, caller): 
     csrf_token = context['csrf_token'] 
     return jinja2.Markup(self.template % unicode(csrf_token)) 

csrf = CsrfExtension 
Verwandte Themen