[Grok-dev] template association - suboptimal magic?
Jan-Wijbrand Kolman
janwijbrand at gmail.com
Thu Sep 4 18:30:32 EDT 2008
Hi,
I'm trying to fix https://bugs.launchpad.net/grok/+bug/255005. In doing
so I more and more get the feeling the way template association works in
Grok (grokcore.view more specifically) is suboptimal magic.
Let me try to summarize my thinking and suggest a possible solution:
Templates are gathered in a template registry during grokking. It is
ensured that this gathering of templates is done before grokking the
view components that might be associated with these templates. Finding
templates pivots around modules: templates can be defined in modules, or
as files in a directory where the name of this directory is derived from
the module name or from the module-level grok.templatedir() directive.
Whenever a view component in a module grokked the template registry is
asked whether this component has a template associated with it. The
registry decides a template is associated with a component when it has a
template for a particular name: the component's classname (lower-cased)
or as defined by a grok.template() directive on the component.
After trying to associate templates with component each template
registry is asked to issue warnings about all templates that it cannot
associate to a view.
I see a couple of problems with the current situation:
* Since template registries are tied to modules a template defined on a
component in one module cannot be used by sublcasses of this component
defined in an other module. This results in a unexpected and difficult
to solve situation for the application developer (the original issue I
tried to solve).
* Whenever you want to (re)use a template file for components in
multiple modules, you have to use grok.templatedir() in each of these
modules. This in itself is not a problem, however it is likely that this
templates directory then contains template files that cannot not be
associated with all components of all modules that make use of this one
"shared" directory.
This results in (lot of) warnings for template files that cannot be
associated to component (remember, each module has its own registry!).
This used to be an error actually in earlier days, preventing you to
follow this pattern at all. I find the warnings especially ironic, since
the developer's intention of reusing template files is perfectly valid.
* If at some point in the development of an application a new component
is introduced with a render() method *and* having a classname that is
resolvable to a template that was created earlier in the development
process, "suddenly" an error is raised. This is annoying to say the least.
* In the current implementation, it is the template registry that
changes the component class associated with it, by setting a template
attribute. I would've expected (while researching the issue) that the
grokker of this (view) component would take care of this.
* There's a lof explanation to do to application developers how the
template association works (and hence there's a lot of code that does
all kinds of checks to help the developer find out in time about
problematic situations in his code).
My sugestion is basically to make the template association simpler by
making it more explicit and use less magic. Let try to sketch out the
"rules":
* The grok.template() directive can be used on a (view) component.
* By absence of the grok.template(...) directive, the component's
grokker decides what to do. Most likely is to require the component to
have a render() method instead.
* The grok.template() directive sets a template name explicitly:
class ViewA(grok.View):
grok.template('sometemplatename')
* The grok.template() directive can be "empty" (i.e. no explicit value
is used). In that case it is the component's classname, lowercased, that
is used for the template name:
class ViewB(grok.View):
grok.template()
Would be equvalent to:
class ViewB(grok.View):
grok.template('viewb')
* The grok.template() directive does a lookup for the template file
corresponding to the template name. The directive implementation stores
the filename:
* It looks for this file in a directory named according to the
module name or as explicitley defined by a grok.templatedir()
directive in this module.
* When it cannot find a template file, or when it finds multiple
files (i.e. with different extensions) it issues an error.
* The (view) component grokker can take the value (filename) from the
grok.template() directive and take appropiate action (e.g. like looking
up the template factory utility or checking for a render() method).
You might notice that there's no registry in play here, still most of
the "exepected" current behaviour is still there and the afformentioned
bug is solved.
There's also something that is lost: templates defined in modules. These
templates need a registry of some sort, since at the time the
grok.template() directive is called, such a template might not yet be
defined.
Now, let me make a wild guess and a blunt statement about templates
defined inside modules: I don't think anyone is using them for real in
applications, so let's get rid of them.
There's another thing that I didn't cover: Although not essential it is
really nice to report about templates that are not used at all. This
helps the developer keep his codebase clean. I think the
grok.templates() directive could keep a global list of templates
filenames and check, late in the grokking process, whether all template
files that can be found for the application actually are used at least once.
Words of warning:
I found the current template association not very easy to follow, so I
might be overlooking essential elements - esp. since I couldn't let go
of this topic for the whole day and it is getting a bit late in the
evening by now.
Also, I have no code yet that illustrate these ideas. I would be willing
to work on this code though. I also realize that it would not be a small
change in grokcore.view and it is already released as 1.0...
Thoughts?
kind regards,
jw
More information about the Grok-dev
mailing list