[Grok-dev] Re: regebro-guido-templates: comments
Brandon Craig Rhodes
brandon at rhodesmill.org
Mon Oct 22 16:11:52 EDT 2007
Martijn Faassen <faassen at startifact.com> writes:
> Thanks for doing this work! We should give it another review and
> then merge. Is someone else volunteering to do a review? What about
> Brandon, for instance?
I've taken a brief look already, and will take a deeper one either
tonight or tomorrow night. My big issue at the moment is that I'm
still skeptical about whether different template languages need
different default namespaces. It seems to me that namespace should
depend on the framekwork, not the template language. That is: it
seems to me that if I use TurboGears, and (I'm making this up) if it
thinks of things in terms of "model", "view", and "controller", then
those ought to be the names available whether I write my templates in
Cheetah or Genshi or anything else. Similarly, once you're in Zope 3,
then the objects beneath your template are going to be a "view", and a
"context", and a "static", etcetera - regardless of template language.
So I'm not sure yet why we would support a template language getting
to supply a different kind of default namespace.
Martijn has asked the question: how can a developer who wants to
"push" template data write code so as to be sure that nothing leaks
through because he accidentially adds to a default Zope namespace
rather than creating one from scratch? At least two answers have been
1. The rule would be: "use the correct extension on your templates."
For example, if they always used ".gr" instead of ".gt", then they
would be running "restricted Genshi" and instead of getting their
"view", "context", etcetera, they would only get what their own
"view.namespace()" method defined, or, if they forgot to supply
it, a safely empty dictionary.
2. The rule would be: "always define namespace() methods returning
dictionaries instead of update() methods setting attributes." If
a namespace method were present, then the default namespace would
be thrown out in favor of calling the user's namespace().
>From what I understand from our brief chat, Martijn advocates the
first, whereas I advocate the second. He seemed to say that it's easy
to check to make sure all your templates have the right extension, but
that it would be harder to write all Views with namespace() methods.
For my part, I don't see that requiring namespace() on each View is
too great a burden.
But: I'm interested in making an alternative suggestion: What if we
used adapters to solve this problem instead?
For example, what if there were an IDefaultNamespace utility type,
and The Rules were:
a) When a View needs to build its namespace for the template, it
calls its own .namespace() method.
b) If the user has overriden this, then the dictionary they return is
used as the namespace.
c) If the user has not overriden .namespace() on their view, then the
default grok.View.namespace() gets called, which calls for the
IDefaultNamespace utility, __call__'s it with itself and the
template as arguments, and then passes the result as the namespace.
d) The default, globally-registered IDefaultNamespace builds the
standard Zope namespace.
e) The user can create, as a local utility on any app he pleases, the
grok.templates.EmptyNamespace utility, which just returns an empty
dictionary. (Or, of course, a utility of his own devising.)
So, if the user did nothing special, then each view would be "push" or
not depending on whether he defined namespace() or not. But, if he
declared "EmptyNamespace" to be the default namespace utility for his
app, then *all* of his views become "push" whether he supplies
namespace() or not; if he doesn't, then an empty namespace is pushed.
This way, "push"-style developers could get the safety Martijn wants
them to have, but without our being saddled with two different
extensions for every single template language just to control an
option that I think should be independent of template language to
begin with. They would simply:
class MyApp(grok.Application, grok.Container):
Anyway, these are the thoughts I'll have in my head as I review the
Besides looking at the Genshi code, what else should I be doing?
Let's list the sorts of things I should try to accomplish soon:
- Write that Zope 3 proposal for the .adapt() method that will change
the world. I'm still trying to figure out what all the different
combinations of named and un-named and local and global adapters
are, and whether all combinations are valid, and if not, why.
- Finish megrok.trails, which just barely works at this point, but
only fragilely. Are those functions available now that let you
write pre- and post-grok actions for your classes? They'll help me
a lot with Trails.
- Finish my tutorial for zalchemy. I was waiting for the new
zalchemy that works with SQLAlchemy 0.4 to be released, but maybe
that won't happen soon and I should write the tutorial anyway?
- I want to write a brief technical note for the web site about how I
wrote my own IAuthentication for writing a CAS-enabled app, which I
just did at work. Twenty lines of code got my own login page
- I should write a short technical note about how, by SSH'ing back to
localhost with "-L 8090:localhost:8080", I can be logged in as an
administrator using HTTP Basic Auth on :8080, then point another
browser tab at :8090 and it not reuse the same Basic Auth password,
so I can log in as a regular user without having to start up a new
- I want to figure out, then document, how to run a Grok instance
with only an in-RAM Data.fs for authentication bookmarks but not
much more, for people whose real data is already in SQL.
- I want to write a short tutorial on what to commit to Subversion so
that your web app will work when you check it back out. I need to
understand first the pros and cons of Zope buildout versus just
supplying "bootstrap.py". The tutorial should also probably have a
second section about backing up Data.fs, or at least pointing at
other resources about handling Data.fs, so that it's a complete
tutorial about storing the entire state of your app, both code and
- I need to ask a question, which I'll do right here: In the web app
I have written, there were two or three pieces of information that
I turned out needing from many different views in my code. I
discovered that if I declared a view:
self.foo = 5
then I could get the value of 'foo' from anywhere in any view by
calling something like:
<b tal:content="context/@@common/foo">the Foo value</b>
Is this a valid design pattern? Or a broken way of getting
something that's much easier to achieve? :-)
Brandon Craig Rhodes brandon at rhodesmill.org http://rhodesmill.org/brandon
More information about the Grok-dev