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.

Reply via email to