Timmy O'Mahony
Timmy O'Mahony

Reputation: 53999

How are django templates parsed?

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?).

Upvotes: 8

Views: 944

Answers (4)

Ski
Ski

Reputation: 14497

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.

Upvotes: 3

Spidfire
Spidfire

Reputation: 5533

I guess they use tokenizing and parsing

a simple way to discribe is:

Tokenizing: break appart the code to types like:

integer foo = "bar" + 15;

this consists of

T_VARIABLETYPE  + T_VARIABLENAME  + T_EQUALS + T_STRING + T_PLUS + T_DIGIT + T_SEMI

after this you can parse by trying to find patterns with a parser

parsing:

find the pattern:

T_VARIABLETYPE  + T_VARIABLENAME  + T_EQUALS + {A recursive thing} + T_SEMI

This way you can execute a command

If you like to experiment with this i could recomend to use "ANTLR" http://www.antlr.org/ Its available in lot of different languages like Java or C# and even PHP and JS

Upvotes: 0

Marcin
Marcin

Reputation: 49856

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.

Upvotes: 3

sepulchered
sepulchered

Reputation: 814

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.

Upvotes: 2

Related Questions