Opened 7 years ago

Closed 4 years ago

#6516 closed Bug (fixed)

Template extends bug when passing a template variable to extends tag

Reported by: AmanKow Owned by: nobody
Component: Template system Version: master
Severity: Normal Keywords: extends template overwrite
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

This is loosely related to #5124, at least the problems lie in the same code where extends resolution occurs during rendering of the ExtendsNode.

Extended templates are fetched at the time that a child template is rendered. This is done to defer fetching the extended template in the case where a variable is used to specify the template, as a context must be available. This occurs in all cases, even when a hard coded string is passed, I assume to avoid having multiple ExtendsNode types in similar fashion to the IncludeNode types.

When an extended template is fetched, it is modified in two ways. First, if the extended template also extends and there is a block in the child template that does not exist in the parent, that block is appended to the parents ExtendsNode nodelist. Second, when the block does exist in the parent, it is inserted into the parent template and block in the parent template is attached to the parent attribute of the inserted block to support block.super.

In the two cases where a template name is passed, either as a variable or hard coded, this does not cause a problem, as the template is fetched from source and discarded after rendering. However in the case where an instantiated template is passed in, the passed in template is modified.

Rendering a template (or it's child) should make no changes to a template that will appear if it is rendered again.

I've included a file that demonstrates the case where the child block is inserted into the parent template with a link to it's super block. The other case should not be too hard to verify with a three layer heirarchy. I've also included a diff that does not fix the problem, but cleans up the code a bit and helps to clarify what is going on.

Attachments (2)

test.py (894 bytes) - added by AmanKow 7 years ago.
Demonstration of the bug.
cleanup.diff (11.1 KB) - added by AmanKow 7 years ago.

Download all attachments as: .zip

Change History (12)

Changed 7 years ago by AmanKow

Demonstration of the bug.

Changed 7 years ago by AmanKow

comment:1 Changed 7 years ago by AmanKow

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset

The included demonstration code demonstrates both kinds of errors.

comment:2 Changed 7 years ago by AmanKow

  • Component changed from Uncategorized to Template system
  • Keywords extends template overwrite added

comment:3 Changed 7 years ago by AmanKow

Note: The bug where child blocks are inserted into the extended template with the extended templates block attached for super access constitutes a leak of BlockNode objects as well. Every time the template is rendered through the child template, the chain of block will continue to grow in the extended template.

comment:4 Changed 7 years ago by AmanKow

cleanup.diff needs to be reconciled with #5124, I will do so when it settles down

comment:5 Changed 7 years ago by AmanKow

Whoops! Sorry. Meant to attach to different ticket. Ignore contains_nontext_2.diff!

comment:6 Changed 7 years ago by jacob

  • Triage Stage changed from Unreviewed to Accepted

If I'm reading this correctly, the correct approach is to make a copy of the parent template when it's a template object. Yes?

comment:7 Changed 4 years ago by julien

  • Type set to Bug

comment:8 Changed 4 years ago by julien

  • Severity set to Normal

comment:9 Changed 4 years ago by vladmos

  • Easy pickings unset
  • Triage Stage changed from Accepted to Unreviewed
  • UI/UX unset

Just run test.py on django trunk, the result seems to be correct:

$ python test.py 
content block in t1 is modified by rendering through t2
t1.render() t1
t2.render() t2t1
t1.render() t1

content block added to t2 when rendering through t3
t1.render() t1
t2.render() t1
t3.render() t3
t2.render() t1

IMO the bug has already been fixed, please review it (in case i didn't get the point).

comment:10 Changed 4 years ago by aaugustin

  • Resolution set to fixed
  • Status changed from new to closed

I confirm the bug was fixed as a side effect of r11862.

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