[Zope3-dev] Brainstorming about browser pages

Roger Ineichen dev at projekt01.ch
Sat Feb 18 16:40:12 EST 2006


Hi Jeff  

> -----Original Message-----
> From: Jeff Shell [mailto:eucci.group at gmail.com] 
> Sent: Saturday, February 18, 2006 8:05 PM
> To: dev at projekt01.ch
> Cc: Steve Alexander; zope3-dev at lists.zope.org
> Subject: Re: [Zope3-dev] Brainstorming about browser pages
> 
> On 2/18/06, Roger Ineichen <dev at projekt01.ch> wrote:
> > Hi Steve
> > >
> > > The advantage of all this is that you need to look in just
> > > one place to
> > > understand a view class.  You don't need to look in both 
> the ZCML and
> > > the Python code, just the Python code.  The ZCML becomes 
> simpler, and
> > > more focused on glueing pieces of Python code together, 
> and less about
> > > what is to be displayed at what URLs.
> >
> > Let my say somthing about that.
> >
> > I like it and I think it's a good way for simplifie view 
> registration
> > for a well defined project but not a fremawork where has to offer
> > a more open API for views.
> 
> > Why not useable in frameworks;
> > because this means you have to use PageTemplates for such a API.
> > But Im OK with this as long we don't propagate this as a reusable
> > concept for the zope3 core or 3rd party applications.
> >
> > I like it more to see real Pyhton view API's where can be used
> > with different templating systems in the future.
> 
> I don't understand what you mean by this. At its most basic, a 'view'
> in Zope 3 is just a multi adapter. It takes a context object (any
> object) and a browser request and provides... Well, whatever it wants
> to provide. Not all views are named. Not all views have page
> templates. See Absolute URL, for example.
> 
> Beyond that, what kind of "open API" do you need? You can have as open
> of an API as you want.


Don't take my comments as the only correct one. This are just
comments focusing on framework or reusable package development.
My comments doesn't allways fit for simply straight forward 
product development. (I don't mean quick an dirty here!)

Perhaps my focus was not clearly described. I was thinking about
views for products like a bugracker where other will apply their
layout. In such products I like to have a open view API as possible.
And I don't like to get HTML and CSS from the product if I have to
customize and apply another layout. This is only possible if you 
offer view classes not including any PageTemplate mixin.

Some bad samples are for this use case:

template = ViewPageTemplateFile('foo.pt')

or 

return "<div class"foo">foo</div>

If a product like a bugtracker contains such a views. I have to 
replace them and can't use the (view) component within a new 
template.

zope.formlib offers a cool way the get rid of hardcoded 
ViewPageTemplateFile(), they offer a NamedTemplate which can be
registred for skins and make the view - template relation 
customizable.

I guess my concerns about views an a open API was more going in 
a direction like:

"View - Template/Skinning - Relation"

I think projects following a target like Steve describes with 
launchpad or you describing below, will not need such a decoupeling
of views and templates. But I think generic frameworks where users
like to apply their layout will need it.

Can you agree on this?

note:
if I use the word "view" most time I mean a python view class
inherited from formlib.xy or BrowserView etc. (perhaps this is confusing)

> I have 3 way multi adapters (context, request, parent view - but not
> content providers) that exist purely for formatting. I kept having to
> display the same core set of information for an Article - format a
> date, turn a user id into a printable name, list tags. There were some
> situations where one of those things needed to be formatted
> differently: in a search results view, the matching 'tags' needed to
> be highlighted. In other views, the 'tags' needed to be links to find
> other Articles with that tag. So I made a browser view type object
> just for this. Another view (the view listing the articles) is what
> calls it and renders the formatted bits that it wants. The adapter is
> queried like "getMultiAdapter((article, self.request, self),
> IFormattedArticleRecord)", with ``self`` referring to a browser view.
> 
> I break things out like this a lot. I also don't use page templates
> very much in these smaller views, but instead use an internal HTML
> generation tool with ideas liberally borrowed from Nevow's stan, and
> an html "helper" class to provide a common API for useful common
> things (helper is an adapter for a request).
> 
>     html = cmsapi.htmlHelperFor(self.request)
>     T = fdlib.tags.builder(indent=2, separator='\n')
>     outer = T.ul(class_='articles')
>     for article in self.context.values():
>         formatted = zapi.getMultiAdapter(
>             (article, self.request, self), IFormattedArticleRecord)
> 
>         outer << T.li(id='art_%s' % zapi.getName(article))[
>             html.linkTextTo(formatted.title, html.url(article)),
>             html.linkTextTo(
>                 '[Delete]', html.viewURL(article, 'delete'), 
> post=True,
>                 confirm="Delete article %s?" % 
> formatted.title, class_='button'
>             ),
>             T.br,
>             T.strong['Modified: '], formatted.modified,
>         ]
> 
>     return unicode(outer)
> 
> Page template free! And sure to make others cringe :).

I can't say something to this part since I don't know 
the API behind.

> If you need an API, make interfaces and make views that provide those
> interfaces. But often, a view is really about output for a particular
> display, and that should really be its main job.
> 
> And if you find yourself formatting or looping or walking a certain
> set of data the same or similar way much of the time, extract that
> into a separate class and use it directly or provide it as an adapter
> or utility. Follow the law of threes: if you do something once, you
> don't need an API for it. If you do it twice, copy and paste and sigh
> but you don't need an API for it. Do it three times, and you should
> probably extract it out into a helper.

...and if you develop a framework, make sure users can apply their
layout with minimal work. Or at least on a well defined place
and avoid that users have to customize views, templates etc.
I guess a well designed product should offer a template layer
(with "layer" I mean development layer not interface.ILayer)
where the custom layout can be integrated.

> > btw, I think this isn't really possible since it exist two
> > base templating pattern (push and pull). But a python view
> > class can always offer a API with the right set of methods and
> > permissions. (MVC)
> 
> Yes it can. It can now. Although 'right set of methods and
> permissions' is a very vague concept. If you design your view properly
> (in my opinion), it should be a small enough unit of work that the
> whole view could be protected by just one permission. This comes down
> to where you place responsibilities - does an object listing view also
> take on responsibilities for cutting, pasting, moving, deleting,
> renaming, etc? I used to say yes, but now I vehemently say 'no!' Move
> those responsibilities off into supporting smaller views, I say! That
> doesn't mean you can't provide a helper API that groups those
> responsibilities into a useful tool, but use that API internally.
> 
> I don't think it should be the primary responsibility of a view object
> to provide an API. Its primarily responsibility should be rendering
> content for output. But again, your view can provide an interface and
> you can program against that. Just make the decision - "am I making
> this object to render output?" or "am I making this object as a helper
> for common operations my views need?" and design appropriately.
> 
> Core API's and concepts should be simple. Look at zope.contentprovider
> - 'update' and 'render'. That's all one really needs. You don't need a
> big API supporting, well, I don't know what you'd want to support.
> That's the responsibility of systems that build on Zope 3, whether its
> a big application like launchpad or an internal CMS framework you use
> to support your own customers. Those systems will have their own
> needs. What's helpful for me may not be helpful for you. What works
> for Plone may not work for an e-commerce solution. I like small
> cooperating components, whether they're views or helpers or models or
> utilities. Others prefer bigger classes that take on more
> responsibilities on their own.

Thanks that you like it,
I proposed and implemented the zope.contentpovider concept.
It was a hard way till others agreed on ;-)

> > If we think about MVC then I would say that such a pattern
> > isn't the right way to mix it with PageTemplate implementation.
> > But that's another part.
> 
> It sounds like you want the C more than the V. Personally, I've always
> had an issue with MVC, which is that in so many cases, Views and
> Controllers really have a tight relationship and for many uses an
> object could be both. In Zope 3, you can use ``template =
> ViewPageTemplateFile('foo.pt')``, but you can also just do what I do
> above and use another HTML generation system. Or use meld3 or any
> other offering available. This isn't a Rails type environment where
> the 'views' are templates of a particular type that are in a special
> directory. You have complete control. I like having my 'views' be
> 'controllers', and be full intelligent Python objects. A template is
> just there to support rendering if I need it. A template is too dumb
> to be a view object in my opinion, and I would hate to see
> restrictions along those lines.

I think it's a question of decoupeling python implementation and
HTML or even other ML's like (XML) templating possiblity.

My target is to get a API for templating systems.
Let me explain it a little more:

We have content type objects (models) storing something.
This objects are security protected if they need.

On the other hand we have views with different permission
and offering access to just to a part ot he model access.

And we have also adapters which extend the model or
adding addtional functionality to the model.

Extended functionality could also located in a view.

What I think is:

Python view classes can offer a API for accessing the 
model or just a part of it. Sometimes the view provides 
also a different permission.

My vision is to find a concept where this views can be used
as a base for different templates and support a easy 
registration. 

I think if a templating system requires a different concept
and such a view doesn't fit you should write a adapter to
this view and not reimplement a different view adapting the 
model again. 

Ok, perhaps this is a little to much for pragmatic 
developers ;-)

> I think my style of development these days could be described as
> MVWBoH (model, view, and a whole bunch of helpers).
> 
> > But I agree with you Steve, I think its a good concept if you
> > use it in project which uses PageTemplates and doesn't need to
> > offer a generic API.
> 
> I think the ``update / render`` pair concept (as an elaborated concept
> of __call__ on view classes) is great. Steve's concept is similar. It
> has nothing to do with page templates, except as a minor
> implementation detail. I think __call__ is about the best generic API
> we can use right now. On top of that, the 'update/render' API used in
> zope.formlib, zope.contentprovider, and zope.viewlet is the best
> extension. Why? Because you can look up smaller 'views' within a
> larger view and get them ready for display, but not run them through
> the rendering stage yet. You can prepare them without having to look
> up a richer API, or wonder whether __init__ has set things up yet, or
> whether some internals won't really be prepared until the rendering
> stage. It's so beautifully simple, and I (personally) have gotten
> terrific mileage out of following that pattern for many of our own
> views.

Thanks for the flowers ;-)
Nice to hear that you like the contentprovider and viewlet 
implementation. It's was a hard way to get other developers
or at least Stephan aggreing on this concept and get the Ok 
to implement it.

Regards
Roger Ineichen

> --
> Jeff Shell
> 



More information about the Zope3-dev mailing list