Flask and Jinja2 with bleach, image HTML not worki

2019-04-12 21:29发布

问题:

I have been creating a small blog for myself for a project, only I, as the user, can access the posting page. I had previously been following a Flask tutorial, the end product of which enables you to post HTML and pass it through the Jinja2 templating, using bleach and Markdown.

In my models.py file, these are the allowed tags.

@staticmethod

def on_changed_body(target, value, oldvalue, initiator):
    allowed_tags = ['a', 'abbr', 'acronym', 'b', 'blockquote', 'code',
                    'em', 'i', 'li', 'ol', 'pre', 'strong', 'ul',
                    'h1', 'h2', 'h3', 'p', 'img', 'video', 'div', 'iframe', 'p', 'br', 'span', 'hr', 'src', 'class']
    target.body_html = bleach.linkify(bleach.clean(
        markdown(value, output_format='html'),
        tags=allowed_tags, strip=False))

I have added some img and embedding tags, as these are important to my blog. I have an example post consisting of some text and an image, which is being saved to the (SQLAlchemy MySQL) database exactly how I have written it. Below is taken straight from the database.

<p>Hello</p>

<img src="https://catastrophicfindings.files.wordpress.com/2012/07/moomin-childhood-memories-260482_829_494.jpg">

<marquee>Bye</marquee>

Also, I have a field below my blog post form that displays a preview of the HTML. The image appears as intended, so I know this is fine, and the <marquee></marquee> tag appears as markup.

In my template file, I am passing this body_html like so.

{% if post.body_html %}
    {{ post.body_html | safe }}
{% else %}
    {{ post.body }}
{% endif %}

When I then navigate to the post in my browser, the image does not appear at all. However the marquee tag appears as <marquee>Bye</marquee>, and on further inspection in the developer console, an <img> tag is appearing in the HTML, just without the 'src' attribute.

Is there any way to fix this? Would this be something in the configuration of Jinja? Is there a way to declare allowed attributes, if this was the solution?

Thank you.

回答1:

A little more patience and some googling proved fruitful, taken straight from the bleach docs:

The attributes kwarg is a whitelist of attributes. It can be a list, in which case the attributes are allowed for any tag, or a dictionary, in which case the keys are tag names (or a wildcard: * for all tags) and the values are lists of allowed attributes.

So, I added a dict of desired attributes into my bleach.clean function in models.py:

 @staticmethod
    def on_changed_body(target, value, oldvalue, initiator):
        allowed_tags = ['a', 'abbr', 'acronym', 'b', 'blockquote', 'code',
                        'em', 'i', 'li', 'ol', 'pre', 'strong', 'ul',
                        'h1', 'h2', 'h3', 'p', 'img', 'video', 'div', 'iframe', 'p', 'br', 'span', 'hr', 'src', 'class']
        allowed_attrs = {'*': ['class'],
                        'a': ['href', 'rel'],
                        'img': ['src', 'alt']}
        target.body_html = bleach.linkify(bleach.clean(
            markdown(value, output_format='html'),
            tags=allowed_tags, strip=False, attributes=allowed_attrs))

And this works fantastically. I will be adjusting it to accommodate embedding also.