Opened 16 years ago

Closed 11 years ago

Last modified 12 months ago

#4555 closed Uncategorized (wontfix)

New html-util/filter: unescape

Reported by: Johan Bergström <bugs@…> Owned by: nobody
Component: Template system Version: dev
Severity: Normal Keywords: unescape util filter
Cc: Triage Stage: Design decision needed
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no


This is bascially a shameless escape "rip". I had the need for it in a specific project; so here it is.
What it does is reverse the effect of escape (ie: &amp; => &).
There are plugs for filter and django.utils.html (precisely as escape).

No documentation as of yet - if you're willing to put this into trunk, i'll gladly contribute docs.

Attachments (1)

django-unescape.patch (2.0 KB) - added by Johan Bergström <bugs@…> 16 years ago.
Patch and test case for unescape

Download all attachments as: .zip

Change History (13)

Changed 16 years ago by Johan Bergström <bugs@…>

Attachment: django-unescape.patch added

Patch and test case for unescape

comment:1 Changed 16 years ago by Simon G. <dev@…>

Triage Stage: UnreviewedDesign decision needed

comment:2 Changed 16 years ago by anonymous

Shouldn't unescaping be the responsibility of the view? The only valid place I can see unescaping is with legacy data or data from another source, neither of which I would put in a template. Unescaping in templates feels as dirty as magic_quotes_gpc.

comment:3 Changed 16 years ago by Johan Bergström <bugs@…>

Hello anonymous; Your suggestion is to punt the filter but keep the util? That's the way I'm currently utilizing this function - but for consistency with escape (available both as util and filter, i personally see no greater harm in leaving this option open for whatever data that may turn up in a template.

comment:4 Changed 16 years ago by James Bennett

This feels like something that might not be necessary with the autoescpaing proposals.

comment:5 in reply to:  4 Changed 16 years ago by Johan Bergström <bugs@…>

Replying to ubernostrum:

This feels like something that might not be necessary with the autoescpaing proposals.

I'm not very current with the autoescaping branch, but how would one handle data that you know is escaped already (let's say you run a ping service where most data recieved is unescaped, but for some reason some of the data is escaped)? I can agree on the lacking necessity for this utility in a template; but this would help as a util.

The only reason i sent in a patch was becase you generally want to have 'reversible' functions avaliable - if this patch better suits in my 'own' branch, feel free to close the ticket!

comment:6 Changed 16 years ago by Malcolm Tredinnick

Resolution: wontfix
Status: newclosed

I don't think this is an appropriate filter for core. The use-cases are a bit too marginal.

comment:7 Changed 11 years ago by anonymous

Easy pickings: unset
Resolution: wontfix
Severity: Normal
Status: closedreopened
Type: Uncategorized
UI/UX: unset

I think this ticket should be re-opened.

Anytime a library gives you escaped HTML (eg. Django Rest Framework's auto-generated documentation) a tag like this is super-useful. Plus, it's just kind of strange that core Django has fifty different template tags/filters to escape/not-escape stuff, but 0 tags/filters to unescape stuff.

comment:8 Changed 11 years ago by anonymous

P.S. Just to be clear, no Django doesn't actually have 50 different tags/filters; it has a bunch, and I was being hyperbolic

comment:9 Changed 11 years ago by Russell Keith-Magee

Resolution: wontfix
Status: reopenedclosed

The reason the unescape tag doesn't exist is because you shouldn't need it. If you're ever in a situation where you need to undo escaping, then you haven't been paying attention to where things have been encoded along the line. The fix isn't to allow code to be bounced back and forth between encoded and unencoded -- it's to make sure you're only ever encoding when you need to be.

comment:10 Changed 11 years ago by Aymeric Augustin

In addition to Russell's answer, if a library hands you escaped HTML, the right place to unescape it is "right when you obtain it", not "in the template engine".

Always work with data in the canonical form, and not in an escaped representation for an arbitrary output format.

comment:11 Changed 11 years ago by anonymous

Well, that'd be lovely ... if my library wasn't handling the view layer also (and therefore preventing me from unescaping the code in the view). However, if Django REST framework is just following a bad practice, it's certainly not reasonable to add a filter just for one bad case. I guess I'll just have to dig through the source for some underscored method to override or something ...

Thanks for the explanation on the re-close!

comment:12 Changed 12 months ago by Collin Anderson

I just want to note that I would use an html_unescape template filter in pretty much every case where I use the striptags filter.

For example, I have a product.html_description field and I may want to auto-generate a meta description like so:

<meta name="description" content="{{ product.html_description|striptags|html_unescape|truncatechars:400 }}">

striptags removes tags, but I also want to replace &mdash; -> and &#x27; -> ' before running it through truncatechars. I especially don't want to truncate in the middle of an &mdash; or other html entity. The template engine will take care of auto-escaping the resulting text to html. (And it's fine if the html is longer than 400 chars as long as the text is <= 400 chars.)

I think some people use the insecure striptags|safe as a workaround to "fix" html entities showing up in output, whereas a striptags|html_unescape would solve the same problem and actually be much more secure.

Or maybe it would help to have an html_to_text filter that is basically just striptags|unescape_html. I assume most people who use striptags also want to html entities unescaped too. Again, it might help cut down on insecure striptags|safe usage.

Note: See TracTickets for help on using tickets.
Back to Top