Opened 17 years ago

Closed 16 years ago

Last modified 12 years ago

#5216 closed (fixed)

Lazy Translation label_tag in new forms

Reported by: anonymous Owned by: anonymous
Component: Forms Version: dev
Severity: Keywords:
Cc: mocksoul@…, mauro@… Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: yes Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

A call to {{field.label_tag}} in a newforms template returns <django.utils.functional.proxy object at 0x941fe6c>

I don't know if this is the right way to handle it, but converting contents to unicode works.

Attachments (5)

label_tag.patch (641 bytes ) - added by anonymous 17 years ago.
label_tag.2.patch (619 bytes ) - added by anonymous 17 years ago.
label_tag.3.patch (585 bytes ) - added by MockSoul <mocksoul@…> 16 years ago.
See comment:8
label_tag.4.patch (597 bytes ) - added by Vadim Fint <mocksoul@…> 16 years ago.
Django patch against [8752].
label_tag.5.patch (1.6 KB ) - added by Vadim Fint <mocksoul@…> 16 years ago.
Django patch against [8752] with regression test.

Download all attachments as: .zip

Change History (22)

comment:1 by anonymous, 17 years ago

Sry the indentation in that first patch screwed up. This one should be better.

by anonymous, 17 years ago

Attachment: label_tag.patch added

by anonymous, 17 years ago

Attachment: label_tag.2.patch added

comment:2 by Malcolm Tredinnick, 17 years ago

This is only covering the symptom, not fixing the problem.

Can you provide some details of your setup, please? Does it happen with the dev server? Or only with mod_python or something like that? Do you have a very short example that exhibits the problem reliably?

I have a suspicion this might be a version of #4796, but I need more details to confirm that.

comment:3 by anonymous, 17 years ago

I'm using mod_python Apache 2.2.4. I haven't used the dev server at all so I don't know if it works with that. Here is an stripped down example:

from django import newforms as forms
from django.utils.translation import ugettext_lazy as _

class ContactForm(forms.Form):
	name = forms.CharField(label=_("Name:"))
	email = forms.EmailField(label=_("E-mail:"))

Then in a view:

form = ContactForm(auto_id=True)
return render_to_response(template_name, context_instance = RequestContext(request, 'form':form))

The template is:

{% load i18n %}
{% if form %}
	<form action="{{link}}" id="mainform" method="post">
	{% if sent %}
	<p>{{ sent }}</p>
	{% endif %}
	{% for field in form %}
		<p>
		{% if field.label %}{{field.label_tag}}<br/>{% endif %}
		{{ field }}</p>
		{% if field.errors %}{{ field.errors }}{% endif %}
	{% endfor %}
	<p class="button"><input type="submit" value="Send" /></p>
	</form>
{% endif %}

If you need more info or if something still isn't clear lmk.

comment:4 by anonymous, 17 years ago

Also I'm using Python 2.4.4, FreeBSD if it make a difference

comment:5 by anonymous, 17 years ago

A further note on this. If the form is redisplayed after submission (ei: there is a validation error) the label comes out fine.

comment:6 by anonymous, 17 years ago

Resolution: duplicate
Status: newclosed

duplicate of #4958

comment:7 by anonymous, 17 years ago

oops, #4958 just corrects the problem in admin interface - but it suggests taht the problem may be outside of the newforms code

comment:8 by MockSoul <mocksoul@…>, 16 years ago

Cc: mocksoul@… added
Resolution: duplicate
Status: closedreopened

The problem IS in newforms code.

Small represent code:

from django import newforms as forms
from django.utils.translation import ugettext_lazy as _

class TestForm(forms.Form):
  f1 = forms.CharField(label=_('f1 label'))
  f2 = forms.CharField(label=_('f2_label'), widget=forms.widgets.TextInput(attrs={'id': 'my_id_f2'}))

f1 = TestForm()

for field in f1:
  print field.label_tag()

Outputs:

(gaf-uni) mocksoul@home ~/workspace/gaf-uni/repos/trunk $ python t2.py
<label for="id_f1">f1 label</label>
<label for="my_id_f2"><django.utils.functional.__proxy__ object at 0xb787b0ec></label>

Deep explantation:

(line 308) id_ = widget.attrs.get('id') or self.auto_id
(line 309) if id_:
(line 310)    attrs = attrs and flatatt(attrs) or ''
(line 311)    contents = '<label for="%s"%s>%s</label>' % (widget.id_for_label(id_), attrs, contents)

Then we use automatic id ("self.auto_id") it is in unicode, so id_ also in unicode and in line 311 all substitution params (including attrs and contents) also converted to unicode. So it forces contents.__unicode__() calling.

If user supplies id as string then id_ will be simple str and thus then expanding arguments in line 311 unicode conversation does not perfomed.

So, I think it's better to force user's label to be unicode object:

  • newforms/forms.py

     
    304304        """
    305305        contents = contents or escape(self.label)
    306306        widget = self.field.widget
    307         id_ = widget.attrs.get('id') or self.auto_id
     307        id_ = smart_unicode(widget.attrs.get('id', '')) or self.auto_id
    308308        if id_:
    309309            attrs = attrs and flatatt(attrs) or ''
    310310            contents = '<label for="%s"%s>%s</label>' % (widget.id_for_label(id_), attrs, contents)

by MockSoul <mocksoul@…>, 16 years ago

Attachment: label_tag.3.patch added

See comment:8

comment:9 by Jacob, 16 years ago

Needs tests: set
Triage Stage: UnreviewedAccepted

comment:10 by anonymous, 16 years ago

I am not sure if this is related but the symptoms are very similar. Same scenario as comment8 but using the dev server. My forms fails with the following error:

DjangoUnicodeDecodeError at /board/post
'ascii' codec can't decode byte 0xe8 in position 0: ordinal not in range(128). You passed in <django.utils.functional.__proxy__ object at 0x87fc64c> (<class 'django.utils.functional.__proxy__'>)

Patch label_tag.3.patch did not fix the problem.
With the following changes to forms.py the form is displayed (and translated) correctly.

--- forms.py    2008-05-11 00:33:29.000000000 +0900
+++ forms.py.my.original        2008-05-11 00:33:57.000000000 +0900
@@ -135,7 +135,7 @@
                 if errors_on_separate_row and bf_errors:
                     output.append(error_row % force_unicode(bf_errors))
                 if bf.label:
-                    label = escape(force_unicode(bf.label))
+                    label = escape(force_unicode(bf.label.__unicode__()))
                     # Only add the suffix if the label does not end in
                     # punctuation.
                     if self.label_suffix:

However still fails when submitting with following error:

Traceback (most recent call last):

  File "/usr/lib/python2.5/site-packages/django/core/servers/basehttp.py", line 277, in run
    self.result = application(self.environ, self.start_response)

  File "/usr/lib/python2.5/site-packages/django/core/servers/basehttp.py", line 631, in __call__
    return self.application(environ, start_response)

  File "/usr/lib/python2.5/site-packages/django/core/handlers/wsgi.py", line 205, in __call__
    response = self.get_response(request)

  File "/usr/lib/python2.5/site-packages/django/core/handlers/base.py", line 120, in get_response
    return debug.technical_500_response(request, *exc_info)

  File "/usr/lib/python2.5/site-packages/django/views/debug.py", line 74, in technical_500_response
    html = get_traceback_html(request, exc_type, exc_value, tb)

  File "/usr/lib/python2.5/site-packages/django/views/debug.py", line 153, in get_traceback_html
    'exception_value': smart_unicode(exc_value, errors='replace'),

  File "/usr/lib/python2.5/site-packages/django/utils/encoding.py", line 37, in smart_unicode
    return force_unicode(s, encoding, strings_only, errors)

  File "/usr/lib/python2.5/site-packages/django/utils/encoding.py", line 60, in force_unicode
    raise DjangoUnicodeDecodeError(s, *e.args)

DjangoUnicodeDecodeError: 'ascii' codec can't decode byte 0xe8 in position 0: ordinal not in range(128). You passed in DjangoUnicodeDecodeError('ascii', '\xe8\xa8\x80\xe8\xaa\x9e\xe3\x82\x92\xe9\x81\xb8\xe6\x8a\x9e', 0, 1, 'ordinal not in range(128)') (<class 'django.utils.encoding.DjangoUnicodeDecodeError'>)

comment:11 by anonymous, 16 years ago

Cc: mauro@… added
Owner: changed from nobody to anonymous
Status: reopenednew

comment:12 by mauro@…, 16 years ago

The following patch solved the issues for both labels and errors, now all gets displayed and translated. (not sure if this is the right fix but it works for me, need testing) (tested on dev server only)

--- /pkgs/django-0.96-7154/django/utils/encoding.py        2008-02-26 00:18:22.000000000 +0900
+++ encoding.py 2008-05-11 01:52:14.000000000 +0900
@@ -33,7 +33,7 @@
     """
     if isinstance(s, Promise):
         # The input is the result of a gettext_lazy() call.
-        return s
+        return s.__unicode__()
     return force_unicode(s, encoding, strings_only, errors)
 
 def force_unicode(s, encoding='utf-8', strings_only=False, errors='strict'):

comment:13 by Vadim Fint <mocksoul@…>, 16 years ago

Mauro, your problem is not the same. My patch was for labels which are returned in html as lazy gettext proxies. But without errors :).
Anyway tests and some analysis needed against current trunk.

by Vadim Fint <mocksoul@…>, 16 years ago

Attachment: label_tag.4.patch added

Django patch against [8752].

comment:14 by Vadim Fint <mocksoul@…>, 16 years ago

milestone: 1.0

Hey, guys! The bug is still can be easily represented in latest django trunk with little code snipped shown in comment:8.

And my 8 month old (!!) patch attachment:label_tag.3.patch still works fine with latest trunk (no tests broken). The only difference is newforms/forms.py -> forms/forms.py :). Thus, I did updaded patch for latest trunk (attachment:label_tag.4.patch against [8752]).

Please review asap, I think such things should go into 1.0, so I'm forcing milestone to 1.0. Sorry, if I'm wrong.

by Vadim Fint <mocksoul@…>, 16 years ago

Attachment: label_tag.5.patch added

Django patch against [8752] with regression test.

comment:15 by Vadim Fint <mocksoul@…>, 16 years ago

I did also included regression test in attachment:label_tag.5.patch.

Without patch, test fails with following error:

======================================================================
FAIL: Doctest: regressiontests.forms.tests.__test__.regression_tests
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/mocksoul/tmp/django-label-tag/trunk/django/test/_doctest.py", line 2180, in runTest
    raise self.failureException(self.format_failure(new.getvalue()))
AssertionError: Failed doctest test for regressiontests.forms.tests.__test__.regression_tests
  File "/home/mocksoul/tmp/django-label-tag/trunk/tests/regressiontests/forms/tests.py", line unknown line number, in regression_tests

----------------------------------------------------------------------
File "/home/mocksoul/tmp/django-label-tag/trunk/tests/regressiontests/forms/tests.py", line ?, in regressiontests.forms.tests.__test__.regression_tests
Failed example:
    print f['field_2'].label_tag()
Expected:
    <label for="field_2_id">field_2</label>
Got:
    <label for="field_2_id"><django.utils.functional.__proxy__ object at 0x8a4c98c></label>

With patch, of course, no error occurs.

Hope, this helps.

comment:16 by Malcolm Tredinnick, 16 years ago

Resolution: fixed
Status: newclosed

(In [8761]) Fixed #5216 -- Fixed a case of a string not being a unicode string.
Thanks to Vadim Fint for the test case.

comment:17 by Jacob, 12 years ago

milestone: 1.0

Milestone 1.0 deleted

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