[Grok-dev] viewlets, pagelets and friends

Darryl Cousins darryl at darrylcousins.net.nz
Thu Aug 16 00:41:03 EDT 2007


Hi Luis,

On Wed, 2007-08-15 at 18:45 +0200, Luis De la Parra wrote:
> hi again,
> 
> Darryl Cousins wrote:
> > 
> > The use of the pagelet concept makes it imperiative to be able to define
> > which interface the registered template provides (usually IPageTemplate or
> > ILayoutTemplate) and also to be able to define a name (possible required
> > by a view) and thirdly to be able to define the macro to be used from
> > within the template (introducing `z3c.macro`_).
> > 
> > For these reasons the  ``grok.template`` has been reinvented in
> > `mars.view`_ to tell the grokker that the view should look up a named
> > template. And templates are now registered as any other component using
> > grokkers. The difference being that the component class is a factory - and
> > therefore named as such.
> > 
> > A template is not bound to a view as an attribute. Instead the view will
> > look up a template in the component registry, a template can then be
> > easily reused by many views (as layout templates usually are) and a view
> > can be created to look up as many templates as it may require (by name or
> > interface depending on design and needs).
> 
> 
> I think I'm starting to get it (finally!) =)
> 
> so I can imagine to have something like:
> 
> ### general layout for my site ###
> 
> class SiteLayout(mars.template.LayoutFactory):
>         grok.context(interface.Interface)
>         grok.template('site_layout.pt')
> 
> #
> 
> so that registers a template which "provides" ILayout and can be found for
> every view/context.
> 
> then I would have
> ###
> class Contact(grok.Model):
>         name = ""
>         email = ""
> 
> class ContactPagelet(mars.view.PageletView):
>         grok.name('index.html')
>         grok.context(Contact)
> 
>         def helper_method_for_my_view(self):
>                 pass
> 
> class ContactTemplate(mars.template.TemplateFactory):
>         grok.template('contact.pt')
>         grok.context(ContactPagelet)
> ##
> 
> the pagelet would look up the layout template and find the SiteLayout, 
> then, if "render" is not defined, it would look up a template implementing
> IPageTemplate (ContactTemplate) and render it...

mars.view.PageletView does have a render view - which looks up an
IPageTemplate and returns the rendered template. mars.view.PageletView
also has a __call__ view that looks up an ILayoutTemplate and returns
the rendered template.

It is not if/or. It is designed to work with z3c.layer.pagelet layer,
defined in mars.layer.IPageletLayer.

Remember that mars is only there to perform registration normally done
with zcml. No more than that. Grok on the other hand adds useful
functionality - eg  Grok.View has methods such as `url`, `redirect` etc.

> just a few questions: 
> 1)do PageTemplates ever provide some extra functionality, or do they
> always "only" render the template file?

Do you mean zope.pagetemplate.pagetemplate.PageTemplate? The interface
describes methods used primarily for reading and rendering.

> 2)Are not PageletViews more or less "hard-wired" to a given template? (a
> template can be used from several pagelets, but a pagelet can only use one
> template)

mars.view.PageletView already use 2 templates, one in render, one in
__call__. A third could be added:

class MyView(mars.view.PageletView):
        grok.name('index.html')
        grok.context(Contact)

        def render_special(self):
               template = zope.component.getMultiAdapter(
                (self, self.request), IMySpecialTemplate)
            return template(self)

Equally I could override the call method if the design called for it.

class MyView(mars.view.PageletView):
        grok.name('index.html')
        grok.context(Contact)

        def __call__(self):
               template = zope.component.getMultiAdapter(
                (self, self.request), IMySpecialTemplate)
            return template(self)

The __call__ and render methods of mars.view views are only there so
that I don't need define those methods and write out
zope.component.getM... everytime I write a view.

Note that mars.form.FormView does not have any methods - it is designed
to be used with z3c.formui.layout mixins which define __call__ methods.

> 
> if those two are correct, I think having to create an extra class for the
> template registration is only boiler-plate code that's not really
> necessary?

I mentioned in my last post 3 things that can be done with the mars
template factories that couldn't be done with
grok.template('path/to/template'), here they are again in more detail
and a fourth added:

1. able to define which interface the registered template provides

For example to tell mars.template.TemplateFactory to provide an
interface other than IPageTemplate::

	class MyTemplate(mars.template.TemplateFactory):
		grok.context(MyView)
		grok.provides(IMySpecialTemplate)

This  template would then be looked up in the `render_special` in the
above MyView class example.

2. able to define a name


	class MyTemplate(mars.template.TemplateFactory):
		grok.context(MyView)
		grok.name('special')

The view then needs to know to look up a ``named`` template:

	class MyView(mars.view.TemplateView):
		grok.template('special')

I've mentioned elsewhere (?) that I have reinvented grok.template for
this use.

3. able to define the macro to be used from within the template

	class MyTemplate(mars.template.TemplateFactory):
		grok.context(MyView)
		mars.template.macro('mymacro')

In this example the template might look like this::

<div>This won't be rendered</div>
<div metal:define-macro="mymacro">This is within the mymacro macro</div>
<div>This won't be rendered</div>

4. able to define content_type

	class MyTemplate(mars.template.TemplateFactory):
		grok.context(MyView)
		mars.template.content_type('text/plain')

I'd need to double check that I have included all these 4 points in
mars.template.ftests (missing the first in tests I think).

> 
> I patched the "Pagelet Grokker" locally in meta.py in mars.view to register
> a template providing IPageTemplate if the grok.template declaration is
> used, so that I can replace the code above for :
<snip>
> and seems to have exactly the same effect as with the two classes... am I
> missing something here/losing "flexibility" or whatever that I might need
> at a later time?
> 
> I also think the pageletgrokker should ensure that a template is registred
> for the pagelet OR it defines a render method, but not both. I don't know
> if such a check would fit in mars or if it would be more grok-like.

Mars does not use the Grok template registration at all, just as it does
not know about 'static'. Mars is not an extension of Grok, nor a
replacement. It is code that uses grok and martian to register
components so that I can sit down and write components in Python code
that includes the registration with the component registry without
having to jump back and forth to .zcml files - which for me was prone to
error and confusion.

Grok conventions are great but I soon found that to use other packages
(z3c.form exactly) I wanted more configuration back in my hands. This is
of course possible by using zcml (and I still do) but I enjoy too much
including configuration directly in my code by subclassing mars or grok
components that I know martian will scan and register for me.

Regards,
Darryl

> 
> regards. luis
> 
> 
> _______________________________________________
> Grok-dev mailing list
> Grok-dev at zope.org
> http://mail.zope.org/mailman/listinfo/grok-dev



More information about the Grok-dev mailing list