Hello, Jonathan
> How exactly do you want to solve dynamic inheritance? It seems that
> some people are still interested in dynamic inheritance, by using
{%
> extends variable %}. (Which is still dirty in my opinion, but
anyway.)
> Block information has to be kept somehow.
For supporting dynamic inheritance compiled template will be looked
more complicated. To resolve this i should :
1.Create class Template_BlockOutput similiar to ContextRender :
class Template_BlockOutput(object):
def __init__(self):
self._levels = [{}]
def __getitem__(self,key):
for level in xrange(0,len(self._levels)) :
if self._levels[level].has_key(key) :
return self._levels[level][key]
raise AttributeError()
def super(self,key):
if len(self._levels) > 1 :
for level in xrange(1,len(self._levels)) :
if self._levels[level].has_key(key) :
return self._levels[level][key]
else :
if self._levels[0].has_key(key) :
return self._levels[key]
else :
return ""
def has_key(self,key):
for level in xrange(0,len(self._levels)) :
if self._levels[level].has_key(key) :
return True
return False
def __setitem__(self,key,value):
self._levels[0][key] = value
def append(self,d):
if isinstance(d, Template_BlockOutput) :
for level in d._levels :
self._levels.append(level)
elif isinstance(d,list) :
for level in d :
self._levels.append(level)
elif isinstance(d,dict) :
self._levels.append(d)
The instance of this class will be named as «blocks_output». Saving
all blocks output is used
for block.super expression.
2.Add list named blocks_sequence_output, that will contain blocks
output sequence. Every time parser will find «extends» tag — the list
will be overridden by parent blocks output sequence.
3.Add get_compiled_template_or_create function to
django.template.loader that will be imported in compiled template for
compiling and importing external template.
To support all that requirements classes BlockNode, ExtendsNode should
contain compile functions like :
class BlockNode(Node):
def super_compile(self):
compiled_code = ["blocks_output.super('%s')" % self.name]
return compiled_code
def compile(self,parent_name):
compiled_childs = self.nodelist.compile(self.name)
compiled_code = ["blocks_output['%s'] = %s" %
(self.name,compiled_childs),
"blocks_sequence_output.append('%s')" %
self.name]
return compiled_code
class ExtendsNode(Node):
def get_parent_compiled(self):
if self.parent_name_expr:
parent = self.parent_name_expr.compile()
else :
parent = self.parent_name
if not parent:
error_msg = "Invalid template name in 'extends' tag:
%r." % parent
if self.parent_name_expr:
error_msg += " Got this from the '%s' variable." %
self.parent_name_expr.token
raise TemplateSyntaxError(error_msg)
if hasattr(parent, 'compile'):
return parent.compile() # parent is a Template object
code = ["extenal_blocks_output,
external_blocks_sequence_output =
get_compiled_template_or_create(%s,no_output=True)" %
self.parent_name,
"blocks_output.append(external_blocks_output)",
"blocks_sequence_output =
external_blocks_sequence_output"]
return code
def compile(self):
compiled_parent = self.get_compiled_parent()
return compiled_parent
And compiled template structure for supporting dynamic template
extending :
from ... import ...
def resolve(context,var_name):
""" should be looked like method _resolve_lookup in
django.template.Variable """
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):
""" compiled template will be here """
""" function footer """
if no_output :
return blocks_output, blocks_output_sequence
else :
output()
Yours Suggestion :
> Maybe one small improvement. Isn't the following
> > date(context.variable or "Default value"),"Y-m-d") faster than
this?
> > date(default(resolve(context,variable),"Default value"),"Y-m-d")
Yes, it will be good to add to every filter function additional
«compile» function that will generate optimesed code. E.g. :
def default_compiled(value, arg):
"""If value is unavailable, use given default."""
return "context.%s or '%s'" % (value,arg)
default_compiled.is_safe = False
register_compiled = Library()
register_compiled.filter(default_compiled) # just like
register.filter()
If in register_compiled filters library hasn't occurred filter,
FilterExpression will use the default filter function registry for
generating : function_name(args) compiled code.
> P.S. I like the cleanness of adding an (optional?) compile method
to
> every Node-derived class.
> But on the other hand, I would like to see Django move to a more
end-
> user-friendly way of defining custom template tags. A way which
does
> not involve any knowledge of the template parser/interpreter/
compiler.
> Of course, that could also be build upon the first.
Class Node should have base function «compile» :
class Node(object):
def genereate_name(self,parent_name):
if parent_name is not None :
self.parent_name = parent_name
else :
self.parent_name = "" # generate uniq name
def compile(self,parent_name):
self.generate_name(parent_name)
compiled_code = ["t = Template('%s')" % self.template,
"blocks_output['%s'] = t._render(context)" %
self.parent_name,
"blocks_output_sequence.append('%s')" %
self.parent_name]
return compiled_code
--
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.