Exercise 3: A Third Block & Duplicate Block Names — Possible Solution ==================================================================== ADDING THE SIDEBAR BLOCK TO BASE ------------------------------ BASE = ''' {% block title %}Default Title{% endblock %} {% block content %}Default content{% endblock %} ''' CHILD = '''{% extends "base" %} {% block content %}Only content overridden.{% endblock %}''' print(render_inheritance(CHILD, {"base": BASE})) RESULT ------------------------------ Default Title Only content overridden. CHILD never defines a "sidebar" block at all, so extract_blocks(CHILD) never adds a "sidebar" key to child_blocks. The replace_block() substitution's own fallback -- child_blocks.get(m.group(1), m.group(2)) -- returns m.group(2), the parent's own captured default body, for any block name not found in that dict. "sidebar" falls back exactly the same way "title" already does in the chapter's own example: this isn't special-cased anywhere, it's the same one fallback rule applying a third time. WHY A DUPLICATE BLOCK NAME WOULD SILENTLY DISCARD ONE ---------------------------------------------------------- extract_blocks() builds its result as a plain dict, keyed by block name: def extract_blocks(template): blocks = {} for m in re.finditer(r'\{%\s*block\s+(\w+)\s*%\}(.*?)\{%\s*endblock\s*%\}', template, re.S): blocks[m.group(1)] = m.group(2) return blocks A dict can only ever hold one value per key. If a child template defined two separate {% block content %}...{% endblock %} pairs, the loop above would run twice for the name "content" -- and the second assignment, blocks['content'] = ..., simply overwrites the first. Nothing raises an error and nothing warns that a block was discarded; the dict has no memory that a first value was ever there at all. VERIFIED DIRECTLY ------------------------------ DUPLICATE_CHILD = '''{% extends "base" %} {% block content %}First content block.{% endblock %} {% block content %}Second content block.{% endblock %}''' print(extract_blocks(DUPLICATE_CHILD)) # {'content': 'Second content block.'} Only "Second content block." survives -- the first block's own text is gone entirely, with no trace it ever existed, purely because it lost a same-key dict write to whichever block happened to be parsed second in source order. WHY THIS WORKS AS AN ANSWER ---------------------------- It extends the chapter's own BASE template using the exact same {% block name %}...{% endblock %} pattern already established, verifies the real fallback behavior with a genuine printed result rather than just asserting it, and traces the duplicate-block-name question back to the concrete dict-overwrite mechanism inside extract_blocks() -- with a real, run test confirming which of the two blocks actually survives and why.