3

I'm working on my website with Flask and Jinja templates, and I have an odd bug about including images in templates. I have a post.html template that inherits from a base.html, and it gets passed a post object from an SQL database. The problem is that some of the Jinja templating functions don't get called when I do so, namely image HTML tags don't load correctly based on the url_for() call. Regular HTML tags are fine, as I use |safe to make they get processed.

Example from the post.html template:

{% extends "base.html" %}
{% block content %}
<div class="post-description">
        <p>
            {{post.body|safe}}       
        </p>
</div>
{% endblock %}

Example from that post.body call:

<b> I work, and am bolded</b>
<img src="{{ url_for('static', filename = 'images/randomImg.png') }}">

While the bold text shows up fine, the url_for is never called. In the outputted source (on the actual website), it's easy to verify, as the src link is never properly represented, unlike other pages where the function is evaluated. If I copy/paste the <img> line so that now my post.html looks like:

{% extends "base.html" %}
{% block content %}
<div class="post-description">
        <p>
            <img src="{{ url_for('static', filename = 'images/randomImg.png') }}">
            {{post.body|safe}}       
        </p>
</div>
{% endblock %}

The first image call loads fine, but the one's inside post.body do not. I'm not sure if there's a Flask or Jinja way to force it to evaluate it, but I'm hoping so.

vvvvv
  • 25,404
  • 19
  • 49
  • 81
Brady S
  • 33
  • 1
  • 5

1 Answers1

2

post.body was not processed the way you want it, because jinja2 does not try to rerender its own output by default, which makes perfect sense.

You could render the post body and then render response:

@app.route("/some/path")
def some_view():
    # ...
    post = Post.query.first()
    rendered_post_body = render_template_string(post.body)
    return render_template("some_template.html", post_body=rendered_post_body)
Bartosz Marcinkowski
  • 6,651
  • 4
  • 39
  • 69
  • I tried your first solution, but I was unable to get the function called still. I quickly just made a "blank.html" file which only contains `{{ data | safe}}`. I then "double called" render_template on it: `render_template('blank.html', data=render_template('blank.html', data=post.body))` with no change unfortunately – Brady S Dec 23 '14 at 08:28
  • You mean that `rendered_post_body` did not contain evaluated `url_for`? If so, could you print `post.body` and `rendered_post_body` inside **view** and provide the output? – Bartosz Marcinkowski Dec 23 '14 at 08:38
  • 1
    You need [`render_template_string`](http://flask.pocoo.org/docs/0.10/api/#flask.render_template_string) not `render_template` for creating the `rendered_post_body`. Remember, the first argument to `render_template` is supposed to be the path to the template. – Sean Vieira Dec 23 '14 at 15:24