Opened 8 years ago

Closed 7 years ago

Last modified 4 years ago

#5216 closed (fixed)

Lazy Translation label_tag in new forms

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

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

Download all attachments as: .zip

Change History (22)

comment:1 Changed 8 years ago by anonymous

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset

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

Changed 8 years ago by anonymous

Changed 8 years ago by anonymous

comment:2 Changed 8 years ago by mtredinnick

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 Changed 8 years ago by anonymous

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 Changed 8 years ago by anonymous

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

comment:5 Changed 8 years ago by anonymous

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 Changed 8 years ago by anonymous

  • Resolution set to duplicate
  • Status changed from new to closed

duplicate of #4958

comment:7 Changed 8 years ago by anonymous

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

comment:8 Changed 7 years ago by MockSoul <mocksoul@…>

  • Cc mocksoul@… added
  • Resolution duplicate deleted
  • Status changed from closed to reopened

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)

Changed 7 years ago by MockSoul <mocksoul@…>

See comment:8

comment:9 Changed 7 years ago by jacob

  • Needs tests set
  • Triage Stage changed from Unreviewed to Accepted

comment:10 Changed 7 years ago by anonymous

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 Changed 7 years ago by anonymous

  • Cc mauro@… added
  • Owner changed from nobody to anonymous
  • Status changed from reopened to new

comment:12 Changed 7 years ago by mauro@…

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 Changed 7 years ago by Vadim Fint <mocksoul@…>

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.

Changed 7 years ago by Vadim Fint <mocksoul@…>

Django patch against [8752].

comment:14 Changed 7 years ago by Vadim Fint <mocksoul@…>

  • milestone set to 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.

Changed 7 years ago by Vadim Fint <mocksoul@…>

Django patch against [8752] with regression test.

comment:15 Changed 7 years ago by Vadim Fint <mocksoul@…>

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 Changed 7 years ago by mtredinnick

  • Resolution set to fixed
  • Status changed from new to closed

(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 Changed 4 years ago by jacob

  • milestone 1.0 deleted

Milestone 1.0 deleted

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