1👍
I maintain a fork of the Inline app. Richard contacted me about this problem and I was able to trace it back to BeautifulSoup, not Django.
The problem was that BeautifulSoup’s replaceWith()
method was being used to replace the inline markup with the rendered template. The result of render_to_string()
is, of course, a string. When replaceWith()
receives a string, it turns it into a NavigableString
. Since BeautifulSoup expects NavigbleString
s to be strings, it assumes they are unsafe and escapes any HTML characters. The result is that the value being returned by Inline’s inlines()
function had a bunch of >
and <
in it rather than <
and >
.
I didn’t notice this problem in Django 1.3,. When I looked, BeautifulSoup was indeed returning escaped HTML. Django’s |safe
template filter must have been unescaping the previously escaped HTML. In Django 1.4, it no longer does that. (And it shouldn’t do that!)
My fix for this is to parse the incoming value with BeautifulSoup and use BeautifulSoup to find all the inline markup, just like before. Rather than using BeautifulSoup’s replaceWith()
method to replace the inline markup with the rendered inline template, I’m now just using Python’s plain old str.replace()
. It feels a bit lame to me, converting the parsed soup back to a string and then doing the string replacement. But it works. I’m partly tempted to just do away with BeautifulSoup altogether and find the inline markup with regular expressions but we all know how that ends. If anybody has a better idea, I’m all ears!
The fix was initially implented in this commit. I improved it in the following commit, but apparently StackOverflow is only allowing me to post a maximum of two links, so you’ll have to find that one yourself!
2👍
Another solution to this is to turn the new code into a BeautifulSoup object, and replaceWith said object. This way beautiful soup seems to behave correctly.
This gives you escaped html:
soup = BeautifulSoup(html_doc)
body = soup.body
new_html = """<p> this is some deap code</p><a href="#">Pointless even</a>"""
body.replaceWith(new_html)
This gives you your html unescapped:
soup = BeautifulSoup(html_doc)
body = soup.body
new_html = """<p> this is some deap code</p><a href="#">Pointless even</a>"""
body.replaceWith(BeautifulSoup(new_html))
- [Django]-Django's Inline Admin: a 'pre-filled' field
- [Django]-Get all values from Django QuerySet plus additional fields from a related model
- [Django]-Django: Why is self. used here?
0👍
It’s because of the render_to_string
here. Go to inlines/app_model.html
and inlines/default.html
and add |safe
after content variables there.