Hi, Jonathan
I was considering two approaches : template compilation with static
inheritance and template compilation with static and dynamic
inheritance.
The first one approach has simple way of compilation :
1.Reading template in string
2.Tokenizing
3.Parsing — creating NodeList structure
4.Recuirsive NodeList tree compiling. Note: parent templatea already
in this tree. And my task is to repeat this structure in python
bytecode.
E.g. Template ('TextNodePart\n{% block some_block %}BlockNode
'some_block'{% if True %}IfNode{% endif %}{%endblock%}') :
from ... import ...
def render(context):
print "TextNodePart"
print "BlockNode 'some_block'"
if True :
print "IfNode"
or, e.g. With static inheritance Template('{% extends 'base.html' %}
SomeTextNode{% block some_block %}{% if True %}ifNode{% endif %}{%
endblock%}'), where base.html — Template('{% block some_block %}{%
endblock %}{% block other_block %}TextNode{% endblock %}') will be
looked :
from … import …
def render(context):
if True :
print "ifNode"
print "TextNode"
But template compilation with dynamic inheritance is a bit more
complicated. Real template structure isn't known at compilation time
of template, because it isn't known what template it will be. At
runtime i tried to find template, compile it, or just import already
compiled template. Structure of final template will be known also at
runtime - thats why I'm collecting blocks output sequence - to output
in this sequence.
E.g. :
child.html :
{% extends parent %}
{% block first_block %}
{% if True %}
some_info
{% endif %}
{% endblock %}
{% block second_block %}
{% endblock %}
parent.html :
TextNode
{% block first_block %}
{% endblock %}
In this example child template has 2 block : first_block and
second_block, but parent template has only 1 block : first_block. And
in this situation I have to print only first_block output...
Compiled child template :
from ... import ...
blocks_output = Template_BlockOutput()
blocks_output_sequence = list()
def output():
for block_name in blocks_output_sequence :
if blocks_output.has_key(block_name) :
print blocks_output[block_name]
def render(context,no_output=False):
blocks_output['first_block'] = '' # entering block tag
blocks_sequence_output.append('first_block')
if True :
blocks_output['first_block'] = blocks_output['first_block'] +
"some_info"
blocks_output['second_block'] = '' # entering block tag
extenal_blocks_output, external_blocks_sequence_output =
get_compiled_template_or_create(context.parent,no_output=True)
blocks_output.append(external_blocks_output)
blocks_sequence_output = external_blocks_sequence_output
""" function footer """
if no_output :
return blocks_output, blocks_output_sequence
else :
output()
Compiled parent template :
from ... import ...
blocks_output = Template_BlockOutput()
blocks_output_sequence = list()
def output():
for block_name in blocks_output_sequence :
if blocks_output.has_key(block_name) :
print blocks_output[block_name]
def render(context,no_output=False):
blocks_output['first_block'] = '' # entering block tag
blocks_sequence_output.append('first_block')
""" function footer """
if no_output :
return blocks_output, blocks_output_sequence
else :
output()
This is draft version of compilation, it has number of defects. I'm
solving them now.
On Apr 1, 12:50 am, Jonathan Slenders <[email protected]>
wrote:
> Another one:
>
> Instead of:
> def has_key(self,key):
> for level in xrange(0,len(self._levels)) :
> if self._levels[level].has_key(key) :
> return True
> return False
>
> do:
> def has_key(self,key):
> return any((key in l) for l in self._levels)
>
> Ony one "self" reference, and any-through-iterator is very fast, as
> it's native python code (probably implemented in C). And lazy
> evaluating.
>
> It's challenging to understand your code. Maybe it's easier if you
> explain in words-only how you want to implement inheritance.
>
> -------------------------
>
> My approach would be like this
>
> For a template called 'x', create a dictionary 'x' with maps the block
> names for this template to a func with it's matching implementation
> code.
> Somehow, a method render_block(name) should be made available. So when
> a blocks are nested, one block should be able to call
> render_block(other_name). The render_block method should do a lookup
> in the dictionary for a block with this name, and call it.
>
> Dynamic inheritance can easily be realized by replacing key/value
> pairs in this dict by other implementations. Pass the original
> implementation to the new implementation as an additional function
> parameter. (As a curry.)
>
> I guess it's fast, and can be cached in memory. For each rendering,
> only a copy of the required template dictionaries have to be made.
> (Not even a deep copy.)
>
> -----------------------
>
> Cheers,
> Jonathan
--
You received this message because you are subscribed to the Google Groups
"Django developers" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/django-developers?hl=en.