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