Opened 16 years ago

Closed 15 years ago

Last modified 13 years ago

#8566 closed (fixed)

mark_safe not propagating from widgets to templates

Reported by: agirman Owned by: nobody
Component: Core (Other) Version: dev
Severity: Keywords: mark_safe, safe string, escape, escaping, widgets
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by Jacob)

I submitted the below to Django Users and Malcolm Tredinnick suggested I open a ticket. Essentially, when making custom widgets, I encountered a problem wherein despite marking things as safe strings, when I tried to render my forms in a template, they were beings escaped. Turning off auto escaping and piping to the safe filter weren't working, and I found that they were being escaped at a very low level. Namely, there is a call in the Widget.render function to django.forms.util.flatatt that is escaping everything. I don't know if this by design or not, but given the number of calls to mark_safe in the Widget module, I suspect not. It is preventing me from, for example, making JS function calls in widgets that require string arguments. I hope this helps.

Regards,

Alex.

====

Hi there,

I have been trying to get a function call into a widget argument, but
have not been able to at the template level, because it would appear
that my safe_strings are being escaped somewhere down in the
framework. I have created a widget and mark_safe'd an attribute
value, but no matter what, since it's pre-escaped by the time it
bubbles up to the template level, I can't not escape it (well... I
could use an html library to de-escape it, but that seems kludgy).

I've traced the execution and found the culprit to be the
django.forms.util.flatatt function. That is:

from django import forms
from django.utils.safestring import mark_safe

class MyWidget(forms.TextInput):
    def __init__(self, *args, **kwargs):
        attrs = kwargs.setdefault('attrs', {})
        attrs['safe_string'] = mark_safe("will o' the wisp")
        attrs['normal_string'] = "cat o' nine tails"
        super(MyWidget, self).__init__(*args, **kwargs)

w = MyWidget()
w.render("field_name", "")

#=> u'<input normal_string="cat o&#39; nine tails" type="text"
name="field_name" safe_string="will o&#39; the wisp" />'

You can see that both the unsafe and safe strings were escaped. I
don't know if this is intentional or not, but it prevents me from
making something like:

<input type="text" onBlur="myFunction('string_arg')">

because it is always escaping my single-quotes. Is this the desired
behavior? Anyway, like I said, the culprit is:

# django.forms.util

def flatatt(attrs):

"""
    Convert a dictionary of attributes to a single
string.
    The returned string will contain a leading space followed by
key="value",
    XML-style pairs.  It is assumed that the keys do not need to be
XML-
escaped.
    If the passed dictionary is empty, then return an empty
string.
    """
    return u''.join([u' %s="%s"' % (k, escape(v)) for k, v in
attrs.items()])  # <-- right there, the escape(v) call... should this
be conditional_escape?

Since there are a lot of calls to mark_safe scattered through the
widget and form-level calls used in rendering, I assume you're meant
to be able to mark something as safe down here and have it get to the
top level unaltered... no?

Change History (6)

comment:1 by agirman, 16 years ago

Alright, I should have previewed. Here is the code in a code block:

class MyWidget(forms.TextInput):
    def __init__(self, *args, **kwargs):
        attrs = kwargs.setdefault('attrs', {})
        attrs['safe_string'] = mark_safe("will o' the wisp")
        attrs['normal_string'] = "cat o' nine tails"
        super(MyWidget, self).__init__(*args, **kwargs)

w = MyWidget()
w.render("field_name", "")
#=> u'<input normal_string="cat o&#39; nine tails" type="text"
name="field_name" safe_string="will o&#39; the wisp" />'


comment:2 by Jacob, 16 years ago

Description: modified (diff)

(fixed formatting)

comment:3 by Malcolm Tredinnick, 16 years ago

Resolution: fixed
Status: newclosed

(In [8601]) Fixed #8566 -- Allow safe-strings in the "attrs" parameter to form widgets.

comment:4 by Denis_Cheremisov, 15 years ago

milestone: 1.01.2
Resolution: fixed
Status: closedreopened

It only propagates unicode safe strings (SafeUnicode), not simple strings (SafeString)

in reply to:  4 comment:5 by Karen Tracey, 15 years ago

milestone: 1.21.0
Resolution: fixed
Status: reopenedclosed

Replying to Denis_Cheremisov:

It only propagates unicode safe strings (SafeUnicode), not simple strings (SafeString)

What is "It"? The committed changeset for this ticket didn't do anything with Safe[Anything], it simply added a call to conditional_escape. conditional_escape, from a quick check, checks for SafeData, the base for both SafeUnicdoe and SafeString. So it isn't at all clear to me what you are trying to report. As the fix for this bug was checked in nearly a year ago, without any immediate reaction that it was broken, it would be best at this point to open a new ticket describing in detail whatever problem you are encountering.

comment:6 by Jacob, 13 years ago

milestone: 1.0

Milestone 1.0 deleted

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