A node is created out of every tag. You can get an idea how it works by reading through how to write custom tags. Anything which is inside the tag will be its children. Here is an example of a comment tag from django docs:
def do_comment(parser, token):
nodelist = parser.parse(('endcomment',))
parser.delete_first_token()
return CommentNode()
as you see comment tag will parse everything until the "endcomment" and will throw it away. Other tags would pass nodelist
to SometagNode()
and will use it for rendering.
Rendering is done recursively. When a render() is called on node it runs render on its children and so on.
Parsing is done recursively as well this is why you can get nested tags and parser.parse()
will manage to find the proper matching closing tag, because when it does parsing and stumbles on a tag it calls do_tag()
thing, which in turn will call the parser.parse()
again to find the nearest closing tag and will wrap everything into a node, return a node, the higher parser.parse() will put it on a node list and will continue to search for the closing tag.
Context object in nodes is a kind of list of dicts structure. Extra context is pushed on top of existing context and passed to children nodes and popped out after node is rendered so that it wouldn't effecting upper scope.
For tags which don't have children the parser.parse()
is not used, and so node instance is returned without any children.