Opened 13 years ago
Closed 11 years ago
#18400 closed Bug (fixed)
Unexpected {% if %} behavior
Reported by: | Florian Apolloner | Owned by: | Susan Tan |
---|---|---|---|
Component: | Template system | Version: | 1.4 |
Severity: | Normal | Keywords: | template, if, length |
Cc: | luyikei, susan.tan.fleckerl@… | Triage Stage: | Accepted |
Has patch: | yes | Needs documentation: | yes |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
Given this simple template string:
{{ asd|length }}{% if asd|length > 1 %}Hi from an non existant variable!{% endif %}
The output will be (if asd is NOT in the context):
0Hi from an non existant variable!
The reason is as follows:
- {{ asd|length }} resolves to ''|length which is 0
- asd|length inside the if resolves to None|length which results in '' (length returns '' for every exception, len(None) isn't valid ;)) and '' > 1 returns True in python :(
The easiest fix I can see is to make the if stuff perform usual template variable resolving which would result in the following patch: https://github.com/apollo13/django/commit/3782fc5862578951b7a6eb1eb97dca3a63267d44
The change breaks the template tests for me, hence I guess this ticket might need a design decission since it breaks behavior (a bit at least apperently ;))
Change History (12)
comment:1 by , 13 years ago
comment:2 by , 13 years ago
Triage Stage: | Unreviewed → Design decision needed |
---|
It would be interesting to investigate why the ignore_failures
argument was added and what it does. Apparently it triggers two different resolution modes. Isn't that inconsistency a bad idea in itself? If so, shouldn't we get rid of this argument?
comment:3 by , 12 years ago
Triage Stage: | Design decision needed → Accepted |
---|
I don't know what the right solution is, but it's definitely a bug.
comment:4 by , 11 years ago
I think that when TypeError happen, length should return 0.
I made pull request at https://github.com/django/django/pull/1633.
In shell if use my patch.
from django import template
t = template.Template("{{ asd|length }}{% if asd|length > 1 %}Hi from an non existant variable!{% endif %}")
c = template.Context({})
print t.render(c)
0
comment:5 by , 11 years ago
Cc: | added |
---|
comment:6 by , 11 years ago
@luyikei the question is how and if that's better than my patch… How many errors do you get in the testsuite with that change? Also any thoughts to the comments from Aymeric?
comment:7 by , 11 years ago
I think it is natural that {{ asd|length }} returns 0.
because actually {{ asd|length }} returns 0.But in {% if asd|length > 1 %} , asd|length returns "".
So it should return 0 I think.
And my patch returns no failures.
comment:8 by , 11 years ago
@luyikei I tested your PR against the test suites in tests/templates and tests/test_templates. A few of the test_template tests fail. Specifically, template_tests/test.py in L620.
I made my own PR here: https://github.com/django/django/pull/1746/ Tests pass, but I am unsure if this fixes the bug. Please feel free to review and provide feedback.
comment:9 by , 11 years ago
Cc: | added |
---|---|
Owner: | changed from | to
Status: | new → assigned |
comment:11 by , 11 years ago
Needs documentation: | set |
---|
Since this is a backwards-incompatible change, it should be documented.
comment:12 by , 11 years ago
Resolution: | → fixed |
---|---|
Status: | assigned → closed |
Hmm, I have an odd issue with the testsuite here:
returns without failures for the patch in question, running the full testsuite results in errors in the testcase in question :(