I have been trying to learn more about Django's templating engine as it's always seemed like a bit of a black box to me. The documentation gives a good outline of the general steps involved and indicates that the template is loaded and parsed, creating a tree of nodes that are rendered (in a cascade?) with a context and appended together to give the result.
What I don't understand is the approach to parsing, and under what criteria the nodes are created? What constitutes a particular node after parsing, and how does this effect the creation of custom template tags (i.e. is there a better and more efficient way to write template tags that would lead to less nodes?).
A Django template is a text document or a Python string marked-up using the Django template language. Some constructs are recognized and interpreted by the template engine. The main ones are variables and tags. A template is rendered with a context.
Template inheritance. The most powerful – and thus the most complex – part of Django's template engine is template inheritance. Template inheritance allows you to build a base “skeleton” template that contains all the common elements of your site and defines blocks that child templates can override.
Django has a built-in templating system called Django template language(DTL). One other popular templating engine that works flawlessly with Django is Jinja2.
To configure the Django template system, go to the settings.py file and update the DIRS to the path of the templates folder. Generally, the templates folder is created and kept in the sample directory where manage.py lives. This templates folder contains all the templates you will create in different Django Apps.
One way of understanding more about the process is to run django with the werkzeug debugger, and trigger an exception in a template. That way, you will be able to view (and interact) with the whole stack up to that point.
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.
I think that first thing you should look at is code.djangoproject.com with django/template/base.py - the first (as Yuji Tomita stated before). Or download sources and look through it with your favorite editor or IDE.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With