Hi,

I'm in the process of upgrading a Django application from 1.5 to 1.6 and 
I've come across a mark_safe + ugettext_lazy issue in form field labels 
that I think might be a bug introduced in 1.6 (possibly related to the 
introduction of the new Form.label_suffix?).

Before reporting it I thought I check here first to see if people think it 
is a bug.

In essence, given a label that is a translatable string containing HTML and 
wrapped in mark_safe, e.g. mark_safe(_("<em>Foo</em>"), calling label_tag 
on the field in a template:

in Django 1.5 results in a non-escaped string: <em>Foo</em>
in Django 1.6 results in an escaped string: &lt;em&gt;Foo&lt;/em&gt;:

(including the default label suffix of ":" for 1.6).

I was expecting 1.6 to render: <em>Foo</em>:

Here's a shell example for 1.5 and 1.6 that distills what I'm getting:

>>> import django
>>> django.get_version()
'1.5.5'
>>> from django import forms
>>> from django.template import Template, Context
>>> from django.utils.safestring import mark_safe
>>> from django.utils.translation import ugettext_lazy as _
>>> class FooForm(forms.Form):
...     foo = forms.IntegerField(label=mark_safe(_("<em>Foo</em>")))
... 
>>> fooForm = FooForm()
>>> fooForm.fields['foo'].label
u'<em>Foo</em>'
>>> Template("{{ f }}").render(Context({'f': fooForm}))
u'<tr><th><label for="id_foo"><em>Foo</em>:</label></th><td><input 
id="id_foo" name="foo" type="text" /></td></tr>'
>>> Template("{{ f.foo.label }}").render(Context({'f': fooForm}))
u'<em>Foo</em>'
>>> Template("{{ f.foo.label_tag }}").render(Context({'f': fooForm}))
u'<label for="id_foo"><em>Foo</em></label>'


>>> import django
>>> django.get_version()
'1.6.1'
>>> from django import forms
>>> from django.template import Template, Context
>>> from django.utils.safestring import mark_safe
>>> from django.utils.translation import ugettext_lazy as _
>>> class FooForm(forms.Form):
...     foo = forms.IntegerField(label=mark_safe(_("<em>Foo</em>")))
... 
>>> fooForm = FooForm()
>>> fooForm.fields['foo'].label
<django.utils.functional.__proxy__ object at 0xabba38c>
>>> Template("{{ f }}").render(Context({'f': fooForm}))
u'<tr><th><label for="id_foo"><em>Foo</em>:</label></th><td><input 
id="id_foo" name="foo" type="number" /></td></tr>'
>>> Template("{{ f.foo.label }}").render(Context({'f': fooForm}))
u'<em>Foo</em>'
>>> Template("{{ f.foo.label_tag }}").render(Context({'f': fooForm}))
u'<label for="id_foo">&lt;em&gt;Foo&lt;/em&gt;:</label>'


It may or may not be related but when I tried delaying the translation as 
described in 
https://docs.djangoproject.com/en/dev/topics/i18n/translation/#other-uses-of-lazy-in-delayed-translations
 
I got a TypeError under 1.6 when passing the lazy object to ugettext:

>>> import django
>>> django.get_version()
'1.5.5'
>>> from django.utils import six  # Python 3 compatibility
>>> from django.utils.functional import lazy
>>> from django.utils.safestring import mark_safe
>>> from django.utils.translation import ugettext_lazy as _
>>> mark_safe_lazy = lazy(mark_safe, six.text_type)
>>> lazy_string = mark_safe_lazy(_("<p>My <strong>string!</strong></p>"))
>>> lazy_string
<django.utils.functional.__proxy__ object at 0x9a0052c>
>>> from django.utils.translation import ugettext
>>> ugettext(lazy_string)
u'<p>My <strong>string!</strong></p>'


>>> import django
>>> django.get_version()
'1.6.1'
>>> from django.utils import six  # Python 3 compatibility
>>> from django.utils.functional import lazy
>>> from django.utils.safestring import mark_safe
>>> from django.utils.translation import ugettext_lazy as _
>>> mark_safe_lazy = lazy(mark_safe, six.text_type)
>>> lazy_string = mark_safe_lazy(_("<p>My <strong>string!</strong></p>"))
>>> lazy_string
<django.utils.functional.__proxy__ object at 0xb00b24c>
>>> from django.utils.translation import ugettext
>>> ugettext(lazy_string)
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File 
".../lib/python2.7/site-packages/django/utils/translation/__init__.py", 
line 76, in ugettext
    return _trans.ugettext(message)
  File 
".../lib/python2.7/site-packages/django/utils/translation/trans_real.py", 
line 281, in ugettext
    return do_translate(message, 'ugettext')
  File 
".../lib/python2.7/site-packages/django/utils/translation/trans_real.py", 
line 256, in do_translate
    eol_message = message.replace(str('\r\n'), 
str('\n')).replace(str('\r'), str('\n'))
  File ".../lib/python2.7/site-packages/django/utils/functional.py", line 
129, in __wrapper__
    raise TypeError("Lazy object returned unexpected type.")
TypeError: Lazy object returned unexpected type.


Any ideas as to whether it may be a bug, or whether I'm just doing it wrong 
and 1.6 has exposed that?

Cheers, Neal

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-users+unsubscr...@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at http://groups.google.com/group/django-users.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-users/926b5932-245f-474d-ba11-9f6ed087f416%40googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to