#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¶m2=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 by , 10 years ago
comment:2 by , 10 years ago
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 by , 10 years ago
Cc: | added |
---|---|
Needs tests: | set |
Triage Stage: | Unreviewed → Accepted |
comment:4 by , 10 years ago
Has patch: | set |
---|---|
Needs tests: | unset |
comment:5 by , 10 years ago
Triage Stage: | Accepted → Ready for checkin |
---|
comment:6 by , 10 years ago
Triage Stage: | Ready for checkin → Accepted |
---|
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.
follow-up: 8 comment:7 by , 10 years ago
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 by , 10 years ago
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 convertingunicode
tostr
"just-like-that" can cause lots of exceptions...
Maybe something like obj.__str__ = lambda s: s.__unicode__().encode('utf-8')
?
comment:9 by , 10 years ago
Patch needs improvement: | unset |
---|
comment:11 by , 10 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
It would be nice to git-bisect the code to find the culprit commit.