Opened 14 years ago

Closed 11 years ago

Last modified 11 years ago

#12064 closed New feature (fixed)

Impossible to conditionally include potentially non-existant templates

Reported by: mkruisselbrink Owned by: nobody
Component: Template system Version: dev
Severity: Normal Keywords:
Cc: FunkyBob 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

It is not possible to conditionally include one template in another template, if the template to include might not exist. The include tag will raise an exception if the template does not exist (and is specified as a string literal, not a variable) even if the actual include tag will never be rendered because a surrounding if statement has a false condition. This can easily be fixed by moving the get_template call from ConstantIncludeNode.__init__ to it's render method.

Attachments (1)

includefix.diff (791 bytes ) - added by mkruisselbrink 14 years ago.
patch that fixes this bug

Download all attachments as: .zip

Change History (18)

comment:1 by mkruisselbrink, 14 years ago

Component: UncategorizedTemplate system

by mkruisselbrink, 14 years ago

Attachment: includefix.diff added

patch that fixes this bug

comment:2 by mkruisselbrink, 14 years ago

Has patch: set

comment:3 by Luke Plant, 14 years ago

Needs tests: set
Owner: changed from nobody to Luke Plant
Status: newassigned

It should be quite easy to produce a test for this bug - no exception should be raised for a template like this:

   {% if some_var_that_equals_False %}
      {% include "some_template_that_does_not_exist.html" %}
   {% endif %}

That test is needed before the patch can go in.

comment:4 by anonymous, 14 years ago

see also: #7931

comment:5 by Luke Plant, 14 years ago

Owner: changed from Luke Plant to nobody
Status: assignednew

comment:6 by Chris Beaven, 14 years ago

The proper fix, assuming this is deemed a valid bug, would be to remove ConstantIncludeNode altogether, not make it work near identically to IncludeNode.

comment:7 by Russell Keith-Magee, 14 years ago

Triage Stage: UnreviewedDesign decision needed

I think this is somewhat related to #12008 - it all hinges on the question of how exactly an {% include %} should be processed -- is it a parsing-level include, or is it a tag that is only evaluated if and when the IncludeNode is rendered?

comment:8 by Matthias Kestenholz, 13 years ago

Ticket #3544 is related too (Fix {% include %} to allow recursive includes) and could be solved at the same time.

comment:9 by Peter Baumgartner, 13 years ago

Severity: Normal
Type: New feature

comment:10 by Tai Lee, 13 years ago

Easy pickings: unset

See also #16147

I believe that the behaviour of {% include %} as it stands is both inconsistent between development (TEMPLATE_DEBUG = True) and production environments, but also within the tag itself depending on the type of argument passed to it. These inconsistencies have shown themselves in a few different buggy (or at least unexpected) ways that are not always easy to trace.

If including a non-existent template is worth raising TemplateDoesNotExist in a development environment, it should not fail silently in a production environment. The exception should also be raised there and redirected to admins via Django's logging.

If including a non-existent template should fail silently when the template does not exist, it should do so both for includes that have a literal string argument or a variable, and it should do so both in development and production environments.

I don't really have a firm opinion on whether or not including missing templates should always fail silently or loudly, although I believe the most common and expected behaviour currently is to fail silently so there may be backwards incompatible issues in changing that. But I do believe that the {% include %} tag should work it's magic at render time for both literal and variable arguments. I consider the currently (undocumented) difference in behaviour to be buggy or at the very least, surprising.

comment:11 by Antti Kaihola, 13 years ago

UI/UX: unset

I'd very much like to see this applied and am willing to contribute to make it happen. We're relying on the silent failure in production, but it's a hassle to comment out the includes when developing in debug mode.

I see that the triage stage for #3544 is "Accepted", and #16147 is "Design decision needed". Would one or both of those fix this issue as well? Should I just write tests for this ticket as lukeplant suggested, or should I direct my efforts at one of the related tickets?

#12008 has been turned into a documentation patch, so it won't help here.

Last edited 13 years ago by Antti Kaihola (previous) (diff)

comment:12 by Preston Timmons, 12 years ago

I added a patch to #16147.

It also addresses the problem of this patch, and lets non-existent templates be conditionally included, even when TEMPLATE_DEBUG is true.

comment:13 by Preston Timmons, 11 years ago

Needs tests: unset

Updated the patch and added a pull request for review.

https://github.com/django/django/pull/920

comment:14 by Jacob, 11 years ago

Resolution: duplicate
Status: newclosed

This is basically a dup of #16147, especially now that there's a patch addressing 'em both at once.

comment:15 by FunkyBob, 11 years ago

Cc: FunkyBob added

I've made a PR for a simpler patch for this:

https://github.com/django/django/pull/1528

comment:16 by loic84, 11 years ago

Triage Stage: Design decision neededReady for checkin
Version: 1.1master

comment:17 by Anssi Kääriäinen <akaariai@…>, 11 years ago

Resolution: duplicatefixed

In e2f06226ea4a38377cdb69f2f5768e4e00c2d88e:

Improved {% include %} implementation

Merged BaseIncludeNode, ConstantIncludeNode and Include node.

This avoids raising TemplateDoesNotExist at parsing time, allows recursion
when passing a literal template name, and should make TEMPLATE_DEBUG behavior
consistant.

Thanks loic84 for help with the tests.

Fixed #3544, fixed #12064, fixed #16147

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