Odd behavior change in 1.8 with {% if %}, RelatedObjectDoesNotExist, and TEMPLATE_STRING_IF_INVALID

138 views
Skip to first unread message

Tim Graham

unread,
Nov 10, 2015, 2:32:36 PM11/10/15
to Django developers (Contributions to Django itself)
I'd appreciate some opinions on whether or not we should treat this issue as a regression: https://code.djangoproject.com/ticket/25600

Yo-Yo Ma

unread,
Nov 10, 2015, 11:12:31 PM11/10/15
to Django developers (Contributions to Django itself)
I may be way off base here, but I actually feel like string_if_invalid should eventually be removed. It seems like a really bad idea to have a setting that can muck up an application in unexpected ways. Meanwhile, settings like DEBUG=True can't muck up your application, even if they're not secure to leave on in production.</digression>

I think the answer to whether it should be treated as a regression is the inverse of whether there are other places where template logic could unexpectedly change based on this setting. Fixing this one situation by checking for a specific error seems wrong, unless it's the only such case that could be reasonably expected to cause this problem. Based on the warning in the docs (about the admin), I take it that is not the case.

So without further ado, I vote "not a regression".

Shai Berger

unread,
Nov 11, 2015, 4:56:03 PM11/11/15
to django-d...@googlegroups.com
On Tuesday 10 November 2015 21:32:36 Tim Graham wrote:
> I'd appreciate some opinions on whether or not we should treat this issue
> as a regression: https://code.djangoproject.com/ticket/25600

Since this is essentially about the `string_if_invalid` configuration option,
whose documentation carries a very clear "For debug purposes only!"
admonition, my inclination is to treat it as a normal bug on the grounds that
it should not affect any production site.

It is still a bug though, I'd like to see it fixed for 1.9.

Shai.

Tim Graham

unread,
Nov 12, 2015, 11:22:24 AM11/12/15
to Django developers (Contributions to Django itself)
The expected behavior of the {% if %} tag isn't clear to me. How do you propose to solve the "bug"? As I noted in the ticket:

We end up checking {% if <string_if_invalid> %} which passes for a non-empty string_if_invalid. I'm not sure we should add special handling of RelatedObjectDoesNotExist in the template engine to restore the old behavior (and I'm not sure how to since RelatedObjectDoesNotExist is a dynamically generated exception based on the related descriptors).

I guess this is related to https://code.djangoproject.com/ticket/17664 which describes inconsistencies in how the if tag silences exceptions.

Carl Meyer

unread,
Nov 12, 2015, 11:51:51 AM11/12/15
to django-d...@googlegroups.com
On 11/12/2015 09:22 AM, Tim Graham wrote:
> The expected behavior of the {% if %} tag isn't clear to me. How do you
> propose to solve the "bug"? As I noted in the ticket:
>
> We end up checking {% if <string_if_invalid> %} which passes for a
> non-empty string_if_invalid. I'm not sure we should add special handling
> of RelatedObjectDoesNotExist in the template engine to restore the old
> behavior (and I'm not sure how to since RelatedObjectDoesNotExist is a
> dynamically generated exception based on the related descriptors).

RelatedObjectDoesNotExist inherits from ObjectDoesNotExist, so we could
catch ObjectDoesNotExist, I suppose. It is possible to construct a
rationale for that: "an object that does not exist should evaluate to
false." But I'm not sure I buy that rationale; I don't like adding more
ad-hoc differing handling of particular exception types in the template
engine.

A better option for resolving this might be to have a dedicated Invalid
type which always evaluates to false in boolean context, but renders
itself as TEMPLATE_STRING_IF_INVALID if asked to coerce to a string.

I guess it could be arguable whether Invalid should be truthy or falsy,
but at least that way it would always be consistent, not dependent on
TEMPLATE_STRING_IF_INVALID.

Carl

signature.asc

Shai Berger

unread,
Nov 12, 2015, 3:29:44 PM11/12/15
to django-d...@googlegroups.com
On Thursday 12 November 2015 18:22:23 Tim Graham wrote:
> The expected behavior of the {% if %} tag isn't clear to me. How do you
> propose to solve the "bug"? As I noted in the ticket:
>
> We end up checking {% if <string_if_invalid> %} which passes for a
> non-empty string_if_invalid.

It seems pretty obvious to me that anything which would be replaced by
string_if_invalid should be falsey. This is because string_if_invalid is
supposed to be a debug aid -- showing when "invalid" happens -- while the
"production" value in a template is an empty string. It is also what happens
for undefined variables, irrespective of string_if_invalid. That is, the bug as
I see it is the mismatch between

{% if undefined %}
This is not rendered, regardless of string_if_invalid
{% endif %}

and

{% if obj.missing_relation %}
This may be rendered, depending on string_if_invalid
{% endif %}

They should be the same (and the former seems less wrong than the latter).

What am I missing?
Reply all
Reply to author
Forward
0 new messages