Opened 7 years ago

Closed 7 years ago

Last modified 7 years ago

#24252 closed Bug (fixed)

reverse_lazy representation

Reported by: Stanislas Guerra Owned by: nobody
Component: Core (URLs) Version: 1.8alpha1
Severity: Normal Keywords: reverse_lazy
Cc: tomas.ehrlich@… Triage Stage: Ready for checkin
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Hi devs,

This is related to #18776 and #24097 I guess.

Since Django-1.8:

my_url = "%s?%s" % (reverse_lazy("foo:bar"), params)

Gives something like:

"<django.utils.functional.__proxy__ object at 0x103563850>?param1=val1&param2=val2"

Prior to 1.8, you'd get a "valid" result.

A workaround is to force the evaluation with an explicit unicode(my_lazy_expression) call.

Is it a bug?
If not, is it worth a note in the release notes?

Change History (12)

comment:1 Changed 7 years ago by Claude Paroz

It would be nice to git-bisect the code to find the culprit commit.

comment:2 Changed 7 years ago by Tomáš Ehrlich

Related PR: https://github.com/django/django/pull/3239
Commit: https://github.com/django/django/commit/c1ef234e310fb984ced37eac8c8b90f5b6155e5f

The problem is when running Python 2.x and it really works in Django 1.7.x.

proxy object for reverse_lazy = lazy(reverse, six.text_type) has defined either __str__ method (in Python 3) or __unicode__ method (in Python 2).

However, when you try to put reverse_lazy into string as described above, the __str__ method is always called (no matter on Python version).

The related part from django.utils.functional is:

            cls._delegate_text = six.text_type in resultclasses
            if cls._delegate_text:
                if six.PY3:
                    cls.__str__ = cls.__text_cast
                else:
                    cls.__unicode__ = cls.__text_cast

comment:3 Changed 7 years ago by Tomáš Ehrlich

Cc: tomas.ehrlich@… added
Needs tests: set
Triage Stage: UnreviewedAccepted

comment:4 Changed 7 years ago by Claude Paroz

Has patch: set
Needs tests: unset

comment:5 Changed 7 years ago by Tim Graham

Triage Stage: AcceptedReady for checkin

comment:6 Changed 7 years ago by Aymeric Augustin

Triage Stage: Ready for checkinAccepted

I don't think it's a good idea to have __str__ return a unicode object instead of a str. This will lead to confusion.

comment:7 Changed 7 years ago by Tomáš Ehrlich

Well, handling of unicode in Python 2 is a little bit confusing to be honest.

The problem is: %s requires __str__ method defined on object and there's no placeholder which would call __unicode__. In Python 3, the %s placeholder requires also __str__, not __bytes__ as one would expect. So, we need to handle, that in Python 2, objects are converted to non-unicode strings (str), while in Python 3 to unicode strings (again str).

Right now, the proxy objects does the *right* thing -- converts objects to unicode strings in both versions. This solutions is logical and seems to be correct, but unfortunately it doesn't work.

We could add obj.__str__ = lambda s: str(s.__unicode__()), but this is exactly what I wanted to avoid because converting unicode to str "just-like-that" can cause lots of exceptions...

comment:8 in reply to:  7 Changed 7 years ago by Claude Paroz

Patch needs improvement: set

Replying to tricoder42:
...

We could add obj.__str__ = lambda s: str(s.__unicode__()), but this is exactly what I wanted to avoid because converting unicode to str "just-like-that" can cause lots of exceptions...

Maybe something like obj.__str__ = lambda s: s.__unicode__().encode('utf-8')?

comment:9 Changed 7 years ago by Claude Paroz

Patch needs improvement: unset

comment:10 Changed 7 years ago by Tomáš Ehrlich

Triage Stage: AcceptedReady for checkin

This looks good

comment:11 Changed 7 years ago by Claude Paroz <claude@…>

Resolution: fixed
Status: newclosed

In cd0ceaa102c1e12b016432db4d180bee7906131f:

Fixed #24252 -- Forced lazy str to utf-8 on Python 2

Thanks Stanislas Guerra for the report and Tomas Ehrlich for
the review.

comment:12 Changed 7 years ago by Claude Paroz <claude@…>

In ea3e40c278eb27fb3c8362d9e8cd67f957bf4f57:

[1.8.x] Fixed #24252 -- Forced lazy str to utf-8 on Python 2

Thanks Stanislas Guerra for the report and Tomas Ehrlich for
the review.
Backport of cd0ceaa102 from master.

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