On 2/18/06, Roger Ineichen <[EMAIL PROTECTED]> 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. 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 :). 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. > 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. > 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 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. -- Jeff Shell _______________________________________________ Zope3-dev mailing list Zope3-dev@zope.org Unsub: http://mail.zope.org/mailman/options/zope3-dev/archive%40mail-archive.com