Jinja2 extension outputs escaped html instead of html tag

送分小仙女□ 提交于 2019-12-13 02:59:40

问题


I'm trying to write a simple jinja2 extension that'll render a <meta> tag in the page with some property and content attr. It looks something like this:

from jinja2 import nodes
from jinja2.ext import Extension

class MetaExtension(Extension):
    """
    returns a meta tag of key, value
    >> env = jinja2.Environment(extensions=[MetaExtension])
    >> env.from_string('{% meta "key", "value" %}').render()
       u'<meta property="keyword" content="value" />'
   """

    # we'll use it in the template with
    tags = set(['meta'])

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

    def parse(self, parser):
        tag = parser.stream.next()
        args = [parser.parse_expression()]

        if parser.stream.skip_if('comma'):
            args.append(parser.parse_expression())

        return nodes.Output([self.call_method('_render', args)]).set_lineno(tag.lineno)

    def _render(self, *args):
        return '<meta property="{}" content="{}" />'.format(args[0], args[1])

meta = MetaExtension

Using it in a flask app:

# register the extension in the app file
from flask import Flask
app = Flask(__name__)
app.jinja_env.add_extension('flask_meta.MetaExtension')

And

<!-- use it in the template -->
<head>
  {% meta "key", "value" %}
</head>

Though the tag renders fine in the console, when I use it in a flask application it escapes the html and outputs the escaped tag to the page. So, instead of

<meta property="keyword" content="value" />

I get

&lt;meta property=&#34;key&#34; content=&#34;value&#34; /&gt;

What am I doing wrong? Thanks.

Update: See my answer below.


回答1:


This code produces...

<meta property="('this', 'that')" content="('this2', 'that2')" />

try this...

from jinja2 import nodes
from flask import Flask
from jinja2.ext import Extension

app = Flask(__name__)

class MetaExtension(Extension):
        """
        returns a meta tag of key, value
        >> env = jinja2.Environment(extensions=[MetaExtension])
        >> env.from_string('{% meta "key", "value" %}').render()
           u'<meta property="keyword" content="value" />'
       """

        # we'll use it in the template with
        tags = set(['meta'])

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

        def parse(self, parser):
            tag = parser.stream.next()
            args = [parser.parse_expression()]

            if parser.stream.skip_if('comma'):
                args.append(parser.parse_expression())

            return nodes.Output([self.call_method('_render', args)]).set_lineno(tag.lineno)

        def _render(self, *args):
            return '<meta property="{0}" content="{1}" />'.format(args[0], args[1])

meta = MetaExtension


@app.route("/")
def index():
    #return 'hi'
    try:
        return MetaExtension._render('', ("this", 'that') , ("this2", 'that2') )
    except  Exception as e:
        print(str(e))

app.jinja_env.add_extension(meta)

if __name__ == "__main__":
    app.run()

Hope this helps!




回答2:


Turns out I should have been using nodes.CallBlock instead of nodes.Output. Applying that change, the parse and _render functions now look like:

...
def parse(self, parser):
    tag = parser.stream.next()
    args = [parser.parse_expression()]

    if parser.stream.skip_if('comma'):
        args.append(parser.parse_expression())

    return nodes.CallBlock(self.call_method('_render', args),
            [], [], []).set_lineno(tag.lineno)

def _render(self, value, name, *args, **kwargs):
    return '<meta property="{}" content="{}" />'.format(value, name)

Hope this helps someone, as Jinja2 extension reference (especially for non-block tags) isn't easy to come by :)



来源:https://stackoverflow.com/questions/29370542/jinja2-extension-outputs-escaped-html-instead-of-html-tag

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!