#8566: mark_safe not propagating from widgets to templates
-------------------------------------+--------------------------------------
Reporter: agirman | Owner: nobody
Status: new | Milestone: 1.0
Component: Core framework | Version: SVN
Resolution: | Keywords: mark_safe, safe string,
escape, escaping, widgets
Stage: Unreviewed | Has_patch: 0
Needs_docs: 0 | Needs_tests: 0
Needs_better_patch: 0 |
-------------------------------------+--------------------------------------
Old description:
> 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' nine tails" type="text"
> name="field_name" safe_string="will o' 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?
New description:
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' nine tails" type="text"
name="field_name" safe_string="will o' 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?
Comment (by jacob):
(fixed formatting)
--
Ticket URL: <http://code.djangoproject.com/ticket/8566#comment:2>
Django Code <http://code.djangoproject.com/>
The web framework for perfectionists with deadlines
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/django-updates?hl=en
-~----------~----~----~----~------~----~------~--~---