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 django-developers@googlegroups.com. To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.