[Twisted-web] Re: Nevow and template like files

Nuutti Kotivuori naked at iki.fi
Tue Sep 5 14:48:08 CDT 2006

Valentino Volonghi aka Dialtone wrote:
> On Tue, 05 Sep 2006 18:13:37 +0300, Nuutti Kotivuori <naked at iki.fi> wrote:
>> First are layout pages. These will provide the general
>> layout and functionality for a set of pages that will make up a
>> section of the site. These pages will contain the actual
>> html/head/body tags and such.
>> Second are the content pages. These pages will fit in a certain layout
>> and provide the actual page content to it. There will be static pages,
>> dynamic status pages and pages with web forms. The layout pages need
>> to be able to dig sections out of the content pages to fill in to the
>> layout; for example additional css/javascript to go into head, sidebar
>> items, actual content.
> I think what you said sounds reasonable. Maybe have a look here:
> http://trac.stiq.it/main/browser/stiq/ui/base.py
> Specifically base.Base class which defines 2 class attributes:
> template and sidebar that are used to fill a sidebar pane and the
> content pane of the macro.html template.  Basically you just use
> macro.html as the basis for all the pages and fill the 2 macro slots
> with a different couple of templates each time.

Thanks! I've looked already at that and it seems nice... except for
two points.

First of all, the content is looked up like this:

| def macro_content(self, ctx):
|     return loaders.xmlfile(self.template+'.html', ignoreDocType=True,
|                            templateDir=conf.TEMPLATE_PATH)

Since I have several patterns in a single file, I would need to append
pattern='content' keyword into that. But if I do that, then the file
will get read once by every macro that uses a pattern from it? That
I'd like to avoid - I'd like to keep the loaders in a class
variable nicely, or a Fragment, or something.

Also, if I say pattern='content', then that loader will throw a hissy
fit if the pattern isn't present. So I'd need a loader that would
return some default value when the .load() method is called and that
sounds like an icky solution again. No worries though, it's easy to

So, any ideas how I could have just one loader that would load the
file once, and then just use normal nevow machinery to fetch the
patterns from it (where it is easier to get a default value if the
pattern does not exist)?

>> Third are so called snippet pages. These will contain a large
>> number of text snippets (with markup) that are re-used on many
>> content pages. These snippets need to be easily includable from the
>> content pages. Some of the snippets are used as is, where as some
>> of the snippets need to be parameterised - the calling code needs
>> to be able to fill in some things easily.
>> Snippet pages are a bit troublesome. I was thinking of making a
>> Fragment that would have the docFactory for such a page. Then that
>> fragment would be instantiated where ever some snippet was to be
>> used, and a simple method would be called on it. This method would
>> get the document, get a pattern from it, call fillSlots a couple
>> times and return it. I could make a macro which does this based on
>> the arguments it receives.
> Seems reasonable.

Actually, I have a bit of a problem there - how do I get the whole
document loaded in the methods I have? I can call
self.docFactory.load() in every method ofcourse, but then the context
is a bit screwy - however, I hesitate to pass in the context that is
available at the time of the first call, since that might come from a
different page each time and I'm not sure if the render/macro methods
are going to be invoked from the correct object and such.

>> But it's all a bit in the air.
>> Things I'd like to avoid or achieve. I wouldn't want the actual
>> xhtml templates to be read many times in the life of the program -
>> it may even be a problem with macros if a page is read once per
>> every pattern used from it - so I'd like for them to be read just
>> once. I'd like a way to have some patterns be optional, so I could
>> provide a default thing to do in case they are not found. And I'd
>> like the lookup of the snippet patterns be somehow pre-done, so
>> that every inclusion of a snippet wouldn't have go to through 1000
>> DOM nodes to find the right part.
> Each template is rendered/parsed once and only once (not because of
> my code, but that's how nevow works) unless you modify it (and it's
> not in a macro, in fact if you modify a template included by a macro
> you have to modify the macro too).

I thought that the rendered/parsed version of the template resided in
the loaders.xmlfile instance that is created - and if I return a new
loaders.xmlfile instance (with a different pattern clause) from
several different macros, then the page would get loaded as many
times. Or if I returned a loaders.xmlfile instance from a render
method, then the file would be parsed on each rendition of the page -
am I wrong?

> patterns are always optional.  pre-doing the pattern lookup can be
> done using self.docFactory as an argument to
> inevow.IQ(self.docFactory).onePattern() either at class level or at
> __init__ level. Another way is to simply load a different template
> for the pattern at class level calling it in another way.  pattern
> lookup anyway doesn't go through 1000 DOM nodes. Nevow does
> precompiling of whatever it can.

Patterns are optional yes, but if I call

  loaders.xmlfile(filename, pattern='foobar')

that will throw an exception if pattern 'foobar' is not present in the
file. So will onePattern(), but that is easily wrapped in a try/catch
block (or I can use patternGenerator which does take a default
argument in some cases) - where as a loader being wrapped doesn't do
anything since the actual loading happens later (when the load()
method is called).

>> So, any suggestions on how to actually go about making this happen?
> What you have in mind already seems good enough.
> HTH.

Thanks - I guess my ideas are somewhat in the ballpark of what it
should be - now I just need to iron out the small problems.

-- Naked

More information about the Twisted-web mailing list