[albatross-users] load_template vs run_template, macros vs lookups

Dave Cole djc at object-craft.com.au
Wed Dec 18 15:47:33 EST 2002


> >>My App class does this:
> >>
> >>    def create_context(self):
> >>        ctx = AppContext(self)
> >>	ctx.load_template('header.html')	
> >>	return ctx
> >>
> >>'header.html' contains a bunch of <al-macro> definitions, and some
> >><al-lookup> definitions.  So the macros and lookups should be
> >>defined before more-or-less anything else happens.

Yes.  The idea behind macros and lookups is that they are application
wide resources.  In order to have the resources available when they
are needed you register them immediately after creating the execution
context.  This is sort of what you are doing above.

class App(...):
    def create_context(self):
        ctx = AppContext(self)
        ctx.run_template_once('macros.html')

The idea behind the "run_template_once" is that when you are running
inside mod_python you only want to load and execute the macros for the
first request served by that Apache child.  Once registered the macros
and lookups can be reused until the child exits.

With that in mind, this is what happens.

* Loading the template creates the tag tree and registers the name of
  the macros.

* Running the template evaluates the expressions in the lookup items
  (<al-item expr="...">) creates the dictionary of content fragments
  associated with the lookup.  It is important to note that the
  content in the lookup items is not evaluated at run time.

* Using the lookup in an <al-value expr="..." lookup="..."> locates
  the lookup by name and uses the result of the expression in
  expr="..." to look up the item content dictionary.  The content
  fragment returned is then executed *in the same context as the
  <al-value> tag which used the lookup*

  Macros are similar.  The expanded content is evaluated in the
  context of the macro user, not the context of where the macro was
  defined.

Normal template processing only has two phases; load, and execute.

Lookups and macros have three phases; load, register, and execute.
The register phase occurs when you run_template().  The execute phase
occurs when you use the lookup or macro in another template.

> Hmmm - looking closer at the code, I don't think it would be valid
> to instanciate the lookups without a run. The reason for this is
> that the lookup key is the result of an eval - doing this eval at
> load time would be breaking the "rules".

The rules are a bit tricky.  I can't see why this wouldn't work
though.

> Possibly the eval could be lazy - essentially defer the eval until
> lookup_html is called for the first time (as I suggested
> before). I've just made the change in a sandbox, and it passes the
> unittests, but I'm not sure I like the change (the diff is against
> the CVS tree version - some fuzz may be required when applying to
> 1.01) - Dave - your thoughts?

The eval could possibly be lazy.  I think if you are using lookup
expressions that resolve to different values for different requests
then you are going to be surprised at some point anyway...

> --- tags.py     15 Dec 2002 08:32:41 -0000      1.103
> +++ tags.py     17 Dec 2002 05:45:51 -0000
> @@ -1046,6 +1046,7 @@
>      def __init__(self, ctx, filename, line_num, attribs):
>          EnclosingTag.__init__(self, ctx, filename, line_num, attribs)
>          self.assert_has_attrib('name')
> +        ctx.register_lookup(self.get_attrib('name'), self)
>          self.item_list = []
>  
>      def append(self, tag):
> @@ -1055,13 +1056,14 @@
>              EnclosingTag.append(self, tag)
>  
>      def to_html(self, ctx):
> -        ctx.register_lookup(self.get_attrib('name'), self)
> -        dict = {}
> -        for item in self.item_list:
> -            dict[item.eval_expr(ctx)] = item
> -        self.item_dict = dict
> +        pass
>  
>      def lookup_html(self, ctx, value):
> +        if not hasattr(self, 'item_dict'):
> +            dict = {}
> +            for item in self.item_list:
> +                dict[item.eval_expr(ctx)] = item
> +            self.item_dict = dict
>          item = self.item_dict.get(value, self.content)
>          item.to_html(ctx)
 
The patch looks fine to me.  Give it a shot and see what breaks.

- Dave

-- 
http://www.object-craft.com.au




More information about the Albatross-users mailing list