Search code examples
pythondjangodjango-templatesdjango-ckeditor

How to display text with HTML-markup? (I use ckeditor)


I heard about the filter |safe, but if I understood correctly, that's unsafe and creates a backdoor for injections.

What are the alternatives to display full posts with formatted text?


Solution

  • I think when you not use the filter of |safe, then output should return as text only with html markup (not rendered as html output).

    But, if you need to exclude some dangerous tags such as <script>location.reload()</script>, you need to handle it with custom templatetag filter..

    I got good answer from: https://stackoverflow.com/a/699483/6396981, via BeautifulSoup.

    from bs4 import BeautifulSoup
    from django import template
    from django.utils.html import escape
    
    register = template.Library()
    INVALID_TAGS = ['script',]
    
    def clean_html(value):
        soup = BeautifulSoup(value)
        for tag in soup.findAll(True):
            if tag.name in INVALID_TAGS:
                # tag.hidden = True # you also can use this.
                tag.replaceWith(escape(tag))
        return soup.renderContents()
    
    # clean_html('<h1>This is heading</h1> and this one is xss injection <script>location.reload()</script>')
    # output:
    # <html><body><h1>This is heading</h1> and this one is xss injection &lt;script&gt;location.reload()&lt;/script&gt;</body></html>
    
    @register.filter
    def safe_exclude(text):
        # eg: {{ post.description|safe_exclude|safe }}
        return clean_html(text)
    

    Hope it usefull..