mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			465 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			465 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| from django.template import NodeList, TemplateSyntaxError
 | |
| from django.template.base import Node
 | |
| from django.template.loader_tags import ExtendsNode
 | |
| from django.test import SimpleTestCase
 | |
| 
 | |
| from ..utils import setup
 | |
| 
 | |
| inheritance_templates = {
 | |
|     "inheritance01": (
 | |
|         "1{% block first %}&{% endblock %}3{% block second %}_{% endblock %}"
 | |
|     ),
 | |
|     "inheritance02": "{% extends 'inheritance01' %}"
 | |
|     "{% block first %}2{% endblock %}{% block second %}4{% endblock %}",
 | |
|     "inheritance03": "{% extends 'inheritance02' %}",
 | |
|     "inheritance04": "{% extends 'inheritance01' %}",
 | |
|     "inheritance05": "{% extends 'inheritance02' %}",
 | |
|     "inheritance06": "{% extends foo %}",
 | |
|     "inheritance07": "{% extends 'inheritance01' %}{% block second %}5{% endblock %}",
 | |
|     "inheritance08": "{% extends 'inheritance02' %}{% block second %}5{% endblock %}",
 | |
|     "inheritance09": "{% extends 'inheritance04' %}",
 | |
|     "inheritance10": "{% extends 'inheritance04' %}      ",
 | |
|     "inheritance11": "{% extends 'inheritance04' %}"
 | |
|     "{% block first %}2{% endblock %}{% block second %}4{% endblock %}",
 | |
|     "inheritance12": "{% extends 'inheritance07' %}{% block first %}2{% endblock %}",
 | |
|     "inheritance13": "{% extends 'inheritance02' %}"
 | |
|     "{% block first %}a{% endblock %}{% block second %}b{% endblock %}",
 | |
|     "inheritance14": (
 | |
|         "{% extends 'inheritance01' %}{% block newblock %}NO DISPLAY{% endblock %}"
 | |
|     ),
 | |
|     "inheritance15": "{% extends 'inheritance01' %}"
 | |
|     "{% block first %}2{% block inner %}inner{% endblock %}{% endblock %}",
 | |
|     "inheritance16": "{% extends 'inheritance15' %}{% block inner %}out{% endblock %}",
 | |
|     "inheritance17": "{% load testtags %}{% block first %}1234{% endblock %}",
 | |
|     "inheritance18": "{% load testtags %}{% echo this that theother %}5678",
 | |
|     "inheritance19": "{% extends 'inheritance01' %}"
 | |
|     "{% block first %}{% load testtags %}{% echo 400 %}5678{% endblock %}",
 | |
|     "inheritance20": (
 | |
|         "{% extends 'inheritance01' %}{% block first %}{{ block.super }}a{% endblock %}"
 | |
|     ),
 | |
|     "inheritance21": (
 | |
|         "{% extends 'inheritance02' %}{% block first %}{{ block.super }}a{% endblock %}"
 | |
|     ),
 | |
|     "inheritance22": (
 | |
|         "{% extends 'inheritance04' %}{% block first %}{{ block.super }}a{% endblock %}"
 | |
|     ),
 | |
|     "inheritance23": (
 | |
|         "{% extends 'inheritance20' %}{% block first %}{{ block.super }}b{% endblock %}"
 | |
|     ),
 | |
|     "inheritance24": "{% extends context_template %}"
 | |
|     "{% block first %}2{% endblock %}{% block second %}4{% endblock %}",
 | |
|     "inheritance25": "{% extends context_template.1 %}"
 | |
|     "{% block first %}2{% endblock %}{% block second %}4{% endblock %}",
 | |
|     "inheritance26": "no tags",
 | |
|     "inheritance27": "{% extends 'inheritance26' %}",
 | |
|     "inheritance 28": "{% block first %}!{% endblock %}",
 | |
|     "inheritance29": "{% extends 'inheritance 28' %}",
 | |
|     "inheritance30": "1{% if optional %}{% block opt %}2{% endblock %}{% endif %}3",
 | |
|     "inheritance31": "{% extends 'inheritance30' %}{% block opt %}two{% endblock %}",
 | |
|     "inheritance32": "{% extends 'inheritance30' %}{% block opt %}two{% endblock %}",
 | |
|     "inheritance33": (
 | |
|         "1{% if optional == 1 %}{% block opt %}2{% endblock %}{% endif %}3"
 | |
|     ),
 | |
|     "inheritance34": "{% extends 'inheritance33' %}{% block opt %}two{% endblock %}",
 | |
|     "inheritance35": "{% extends 'inheritance33' %}{% block opt %}two{% endblock %}",
 | |
|     "inheritance36": (
 | |
|         "{% for n in numbers %}_{% block opt %}{{ n }}{% endblock %}{% endfor %}_"
 | |
|     ),
 | |
|     "inheritance37": "{% extends 'inheritance36' %}{% block opt %}X{% endblock %}",
 | |
|     "inheritance38": "{% extends 'inheritance36' %}{% block opt %}X{% endblock %}",
 | |
|     "inheritance39": (
 | |
|         "{% extends 'inheritance30' %}{% block opt %}new{{ block.super }}{% endblock %}"
 | |
|     ),
 | |
|     "inheritance40": (
 | |
|         "{% extends 'inheritance33' %}{% block opt %}new{{ block.super }}{% endblock %}"
 | |
|     ),
 | |
|     "inheritance41": (
 | |
|         "{% extends 'inheritance36' %}{% block opt %}new{{ block.super }}{% endblock %}"
 | |
|     ),
 | |
|     "inheritance42": "{% extends 'inheritance02'|cut:' ' %}",
 | |
|     "inheritance_empty": "{% extends %}",
 | |
|     "extends_duplicate": "{% extends 'base.html' %}{% extends 'base.html' %}",
 | |
|     "duplicate_block": (
 | |
|         "{% extends 'base.html' %}{% block content %}2{% endblock %}{% block content %}"
 | |
|         "4{% endblock %}"
 | |
|     ),
 | |
| }
 | |
| 
 | |
| 
 | |
| class InheritanceTests(SimpleTestCase):
 | |
|     libraries = {"testtags": "template_tests.templatetags.testtags"}
 | |
| 
 | |
|     @setup(inheritance_templates)
 | |
|     def test_inheritance01(self):
 | |
|         """
 | |
|         Standard template with no inheritance
 | |
|         """
 | |
|         output = self.engine.render_to_string("inheritance01")
 | |
|         self.assertEqual(output, "1&3_")
 | |
| 
 | |
|     @setup(inheritance_templates)
 | |
|     def test_inheritance02(self):
 | |
|         """
 | |
|         Standard two-level inheritance
 | |
|         """
 | |
|         output = self.engine.render_to_string("inheritance02")
 | |
|         self.assertEqual(output, "1234")
 | |
| 
 | |
|     @setup(inheritance_templates)
 | |
|     def test_inheritance03(self):
 | |
|         """
 | |
|         Three-level with no redefinitions on third level
 | |
|         """
 | |
|         output = self.engine.render_to_string("inheritance03")
 | |
|         self.assertEqual(output, "1234")
 | |
| 
 | |
|     @setup(inheritance_templates)
 | |
|     def test_inheritance04(self):
 | |
|         """
 | |
|         Two-level with no redefinitions on second level
 | |
|         """
 | |
|         output = self.engine.render_to_string("inheritance04")
 | |
|         self.assertEqual(output, "1&3_")
 | |
| 
 | |
|     @setup(inheritance_templates)
 | |
|     def test_inheritance05(self):
 | |
|         """
 | |
|         Two-level with double quotes instead of single quotes
 | |
|         """
 | |
|         output = self.engine.render_to_string("inheritance05")
 | |
|         self.assertEqual(output, "1234")
 | |
| 
 | |
|     @setup(inheritance_templates)
 | |
|     def test_inheritance06(self):
 | |
|         """
 | |
|         Three-level with variable parent-template name
 | |
|         """
 | |
|         output = self.engine.render_to_string("inheritance06", {"foo": "inheritance02"})
 | |
|         self.assertEqual(output, "1234")
 | |
| 
 | |
|     @setup(inheritance_templates)
 | |
|     def test_inheritance07(self):
 | |
|         """
 | |
|         Two-level with one block defined, one block not defined
 | |
|         """
 | |
|         output = self.engine.render_to_string("inheritance07")
 | |
|         self.assertEqual(output, "1&35")
 | |
| 
 | |
|     @setup(inheritance_templates)
 | |
|     def test_inheritance08(self):
 | |
|         """
 | |
|         Three-level with one block defined on this level, two blocks
 | |
|         defined next level
 | |
|         """
 | |
|         output = self.engine.render_to_string("inheritance08")
 | |
|         self.assertEqual(output, "1235")
 | |
| 
 | |
|     @setup(inheritance_templates)
 | |
|     def test_inheritance09(self):
 | |
|         """
 | |
|         Three-level with second and third levels blank
 | |
|         """
 | |
|         output = self.engine.render_to_string("inheritance09")
 | |
|         self.assertEqual(output, "1&3_")
 | |
| 
 | |
|     @setup(inheritance_templates)
 | |
|     def test_inheritance10(self):
 | |
|         """
 | |
|         Three-level with space NOT in a block -- should be ignored
 | |
|         """
 | |
|         output = self.engine.render_to_string("inheritance10")
 | |
|         self.assertEqual(output, "1&3_")
 | |
| 
 | |
|     @setup(inheritance_templates)
 | |
|     def test_inheritance11(self):
 | |
|         """
 | |
|         Three-level with both blocks defined on this level, but none on
 | |
|         second level
 | |
|         """
 | |
|         output = self.engine.render_to_string("inheritance11")
 | |
|         self.assertEqual(output, "1234")
 | |
| 
 | |
|     @setup(inheritance_templates)
 | |
|     def test_inheritance12(self):
 | |
|         """
 | |
|         Three-level with this level providing one and second level
 | |
|         providing the other
 | |
|         """
 | |
|         output = self.engine.render_to_string("inheritance12")
 | |
|         self.assertEqual(output, "1235")
 | |
| 
 | |
|     @setup(inheritance_templates)
 | |
|     def test_inheritance13(self):
 | |
|         """
 | |
|         Three-level with this level overriding second level
 | |
|         """
 | |
|         output = self.engine.render_to_string("inheritance13")
 | |
|         self.assertEqual(output, "1a3b")
 | |
| 
 | |
|     @setup(inheritance_templates)
 | |
|     def test_inheritance14(self):
 | |
|         """
 | |
|         A block defined only in a child template shouldn't be displayed
 | |
|         """
 | |
|         output = self.engine.render_to_string("inheritance14")
 | |
|         self.assertEqual(output, "1&3_")
 | |
| 
 | |
|     @setup(inheritance_templates)
 | |
|     def test_inheritance15(self):
 | |
|         """
 | |
|         A block within another block
 | |
|         """
 | |
|         output = self.engine.render_to_string("inheritance15")
 | |
|         self.assertEqual(output, "12inner3_")
 | |
| 
 | |
|     @setup(inheritance_templates)
 | |
|     def test_inheritance16(self):
 | |
|         """
 | |
|         A block within another block (level 2)
 | |
|         """
 | |
|         output = self.engine.render_to_string("inheritance16")
 | |
|         self.assertEqual(output, "12out3_")
 | |
| 
 | |
|     @setup(inheritance_templates)
 | |
|     def test_inheritance17(self):
 | |
|         """
 | |
|         {% load %} tag (parent -- setup for exception04)
 | |
|         """
 | |
|         output = self.engine.render_to_string("inheritance17")
 | |
|         self.assertEqual(output, "1234")
 | |
| 
 | |
|     @setup(inheritance_templates)
 | |
|     def test_inheritance18(self):
 | |
|         """
 | |
|         {% load %} tag (standard usage, without inheritance)
 | |
|         """
 | |
|         output = self.engine.render_to_string("inheritance18")
 | |
|         self.assertEqual(output, "this that theother5678")
 | |
| 
 | |
|     @setup(inheritance_templates)
 | |
|     def test_inheritance19(self):
 | |
|         """
 | |
|         {% load %} tag (within a child template)
 | |
|         """
 | |
|         output = self.engine.render_to_string("inheritance19")
 | |
|         self.assertEqual(output, "140056783_")
 | |
| 
 | |
|     @setup(inheritance_templates)
 | |
|     def test_inheritance20(self):
 | |
|         """
 | |
|         Two-level inheritance with {{ block.super }}
 | |
|         """
 | |
|         output = self.engine.render_to_string("inheritance20")
 | |
|         self.assertEqual(output, "1&a3_")
 | |
| 
 | |
|     @setup(inheritance_templates)
 | |
|     def test_inheritance21(self):
 | |
|         """
 | |
|         Three-level inheritance with {{ block.super }} from parent
 | |
|         """
 | |
|         output = self.engine.render_to_string("inheritance21")
 | |
|         self.assertEqual(output, "12a34")
 | |
| 
 | |
|     @setup(inheritance_templates)
 | |
|     def test_inheritance22(self):
 | |
|         """
 | |
|         Three-level inheritance with {{ block.super }} from grandparent
 | |
|         """
 | |
|         output = self.engine.render_to_string("inheritance22")
 | |
|         self.assertEqual(output, "1&a3_")
 | |
| 
 | |
|     @setup(inheritance_templates)
 | |
|     def test_inheritance23(self):
 | |
|         """
 | |
|         Three-level inheritance with {{ block.super }} from parent and
 | |
|         grandparent
 | |
|         """
 | |
|         output = self.engine.render_to_string("inheritance23")
 | |
|         self.assertEqual(output, "1&ab3_")
 | |
| 
 | |
|     @setup(inheritance_templates)
 | |
|     def test_inheritance24(self):
 | |
|         """
 | |
|         Inheritance from local context without use of template loader
 | |
|         """
 | |
|         context_template = self.engine.from_string(
 | |
|             "1{% block first %}_{% endblock %}3{% block second %}_{% endblock %}"
 | |
|         )
 | |
|         output = self.engine.render_to_string(
 | |
|             "inheritance24", {"context_template": context_template}
 | |
|         )
 | |
|         self.assertEqual(output, "1234")
 | |
| 
 | |
|     @setup(inheritance_templates)
 | |
|     def test_inheritance25(self):
 | |
|         """
 | |
|         Inheritance from local context with variable parent template
 | |
|         """
 | |
|         context_template = [
 | |
|             self.engine.from_string("Wrong"),
 | |
|             self.engine.from_string(
 | |
|                 "1{% block first %}_{% endblock %}3{% block second %}_{% endblock %}"
 | |
|             ),
 | |
|         ]
 | |
|         output = self.engine.render_to_string(
 | |
|             "inheritance25", {"context_template": context_template}
 | |
|         )
 | |
|         self.assertEqual(output, "1234")
 | |
| 
 | |
|     @setup(inheritance_templates)
 | |
|     def test_inheritance26(self):
 | |
|         """
 | |
|         Set up a base template to extend
 | |
|         """
 | |
|         output = self.engine.render_to_string("inheritance26")
 | |
|         self.assertEqual(output, "no tags")
 | |
| 
 | |
|     @setup(inheritance_templates)
 | |
|     def test_inheritance27(self):
 | |
|         """
 | |
|         Inheritance from a template that doesn't have any blocks
 | |
|         """
 | |
|         output = self.engine.render_to_string("inheritance27")
 | |
|         self.assertEqual(output, "no tags")
 | |
| 
 | |
|     @setup(inheritance_templates)
 | |
|     def test_inheritance_28(self):
 | |
|         """
 | |
|         Set up a base template with a space in it.
 | |
|         """
 | |
|         output = self.engine.render_to_string("inheritance 28")
 | |
|         self.assertEqual(output, "!")
 | |
| 
 | |
|     @setup(inheritance_templates)
 | |
|     def test_inheritance29(self):
 | |
|         """
 | |
|         Inheritance from a template with a space in its name should work.
 | |
|         """
 | |
|         output = self.engine.render_to_string("inheritance29")
 | |
|         self.assertEqual(output, "!")
 | |
| 
 | |
|     @setup(inheritance_templates)
 | |
|     def test_inheritance30(self):
 | |
|         """
 | |
|         Base template, putting block in a conditional {% if %} tag
 | |
|         """
 | |
|         output = self.engine.render_to_string("inheritance30", {"optional": True})
 | |
|         self.assertEqual(output, "123")
 | |
| 
 | |
|     # Inherit from a template with block wrapped in an {% if %} tag
 | |
|     # (in parent), still gets overridden
 | |
|     @setup(inheritance_templates)
 | |
|     def test_inheritance31(self):
 | |
|         output = self.engine.render_to_string("inheritance31", {"optional": True})
 | |
|         self.assertEqual(output, "1two3")
 | |
| 
 | |
|     @setup(inheritance_templates)
 | |
|     def test_inheritance32(self):
 | |
|         output = self.engine.render_to_string("inheritance32")
 | |
|         self.assertEqual(output, "13")
 | |
| 
 | |
|     @setup(inheritance_templates)
 | |
|     def test_inheritance33(self):
 | |
|         """
 | |
|         Base template, putting block in a conditional {% if %} tag
 | |
|         """
 | |
|         output = self.engine.render_to_string("inheritance33", {"optional": 1})
 | |
|         self.assertEqual(output, "123")
 | |
| 
 | |
|     @setup(inheritance_templates)
 | |
|     def test_inheritance34(self):
 | |
|         """
 | |
|         Inherit from a template with block wrapped in an {% if %} tag
 | |
|         (in parent), still gets overridden
 | |
|         """
 | |
|         output = self.engine.render_to_string("inheritance34", {"optional": 1})
 | |
|         self.assertEqual(output, "1two3")
 | |
| 
 | |
|     @setup(inheritance_templates)
 | |
|     def test_inheritance35(self):
 | |
|         """
 | |
|         Inherit from a template with block wrapped in an {% if %} tag
 | |
|         (in parent), still gets overridden
 | |
|         """
 | |
|         output = self.engine.render_to_string("inheritance35", {"optional": 2})
 | |
|         self.assertEqual(output, "13")
 | |
| 
 | |
|     @setup(inheritance_templates)
 | |
|     def test_inheritance36(self):
 | |
|         """
 | |
|         Base template, putting block in a {% for %} tag
 | |
|         """
 | |
|         output = self.engine.render_to_string("inheritance36", {"numbers": "123"})
 | |
|         self.assertEqual(output, "_1_2_3_")
 | |
| 
 | |
|     @setup(inheritance_templates)
 | |
|     def test_inheritance37(self):
 | |
|         """
 | |
|         Inherit from a template with block wrapped in an {% for %} tag
 | |
|         (in parent), still gets overridden
 | |
|         """
 | |
|         output = self.engine.render_to_string("inheritance37", {"numbers": "123"})
 | |
|         self.assertEqual(output, "_X_X_X_")
 | |
| 
 | |
|     @setup(inheritance_templates)
 | |
|     def test_inheritance38(self):
 | |
|         """
 | |
|         Inherit from a template with block wrapped in an {% for %} tag
 | |
|         (in parent), still gets overridden
 | |
|         """
 | |
|         output = self.engine.render_to_string("inheritance38")
 | |
|         self.assertEqual(output, "_")
 | |
| 
 | |
|     # The super block will still be found.
 | |
|     @setup(inheritance_templates)
 | |
|     def test_inheritance39(self):
 | |
|         output = self.engine.render_to_string("inheritance39", {"optional": True})
 | |
|         self.assertEqual(output, "1new23")
 | |
| 
 | |
|     @setup(inheritance_templates)
 | |
|     def test_inheritance40(self):
 | |
|         output = self.engine.render_to_string("inheritance40", {"optional": 1})
 | |
|         self.assertEqual(output, "1new23")
 | |
| 
 | |
|     @setup(inheritance_templates)
 | |
|     def test_inheritance41(self):
 | |
|         output = self.engine.render_to_string("inheritance41", {"numbers": "123"})
 | |
|         self.assertEqual(output, "_new1_new2_new3_")
 | |
| 
 | |
|     @setup(inheritance_templates)
 | |
|     def test_inheritance42(self):
 | |
|         """
 | |
|         Expression starting and ending with a quote
 | |
|         """
 | |
|         output = self.engine.render_to_string("inheritance42")
 | |
|         self.assertEqual(output, "1234")
 | |
| 
 | |
|     @setup(inheritance_templates)
 | |
|     def test_inheritance_empty(self):
 | |
|         with self.assertRaisesMessage(
 | |
|             TemplateSyntaxError, "'extends' takes one argument"
 | |
|         ):
 | |
|             self.engine.render_to_string("inheritance_empty")
 | |
| 
 | |
|     @setup(inheritance_templates)
 | |
|     def test_extends_duplicate(self):
 | |
|         msg = "'extends' cannot appear more than once in the same template"
 | |
|         with self.assertRaisesMessage(TemplateSyntaxError, msg):
 | |
|             self.engine.render_to_string("extends_duplicate")
 | |
| 
 | |
|     @setup(inheritance_templates)
 | |
|     def test_duplicate_block(self):
 | |
|         msg = "'block' tag with name 'content' appears more than once"
 | |
|         with self.assertRaisesMessage(TemplateSyntaxError, msg):
 | |
|             self.engine.render_to_string("duplicate_block")
 | |
| 
 | |
| 
 | |
| class ExtendsNodeTests(SimpleTestCase):
 | |
|     def test_extends_node_repr(self):
 | |
|         extends_node = ExtendsNode(
 | |
|             nodelist=NodeList([]),
 | |
|             parent_name=Node(),
 | |
|             template_dirs=[],
 | |
|         )
 | |
|         self.assertEqual(repr(extends_node), "<ExtendsNode: extends None>")
 |