Responding to myself, I've actually checked in this feature on the trunk too.
Chris McDonough wrote: > So... to stop hijacking Robert's idea for a directive which spells an > owrap for a view... I have a slightly different idea for this. > > We could allow a ZCML "inner" view directive to spell a "wrapper view > name" ala: > > <view > name="owrap" > view=".views.owrap_view" > template="templates/owrap.pt" > /> > > <view > name="myview" > view=".views.my_view" > wrapper="owrap" > /> > > Note that the "owrap" view above uses the new "template" feature > recently checked in on the trunk, which makes it possible to associate a > view with a template (the view must return a dictionary for this to take > effect). > > The "myview" view declaration indicates that its wrapper is "owrap". > This means that it should first render itself, then pass its own result > into the view found using the current context and request plus a view > name. To this end, we'd wrap the view callable specified by the > directive using a view wrapper something like this: > > from repoze.bfg.view import render_view_to_response > > def owrap_view(view, wrapper_viewname): > if not wrapper_viewname: > return view > def _owrapped_view(context, request): > response = view(context, request) > request.wrapped_response = response > request.wrapped_body = response.body > return render_view_to_response(context, request, wrapper_viewname) > return _owrapped_view > > The "owrap_view" mentioned in the above ZCML would then need to be > implemented like so: > > def owrap_view(context, request): > return {'body':request.wrapped_body} > > The "my_view" view could be something like this: > > from webob import Response > > def my_view(context, request): > return Response('OK') > > The owrap template might look like so: > > <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" > "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> > <html xmlns="http://www.w3.org/1999/xhtml" > xmlns:tal="http://xml.zope.org/namespaces/tal"> > <body> > <div>header</div> > <div tal:replace="structure body" /> > <div>footer</div> > </body> > </html> > > The ultimate result of rendering ""my_view" would eventually be: > > <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" > "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> > <html xmlns="http://www.w3.org/1999/xhtml"> > <body> > <div>header</div> > OK > <div>footer</div> > </body> > </html> > > Make sense? > > > Robert Marianski wrote: >> On Mon, Aug 24, 2009 at 10:11:04PM -0400, Chris McDonough wrote: >>> I like this. >>> >>> Some variations: >>> >>> - Have IOWrap be a multiadapter on context and request, so we can >>> vary the o-wrap based on request type too (e.g. "IManagementRequest" >>> vs. "IRetailRequest"). >> >> Good idea. I'll go ahead and add this in. >> >>> - If IOWrap can't be adapted, just return the result of the view >>> (instead of throwing a component lookup error). >> >> I'm kind of torn on this. On the one hand, I like that a specific >> exception would get thrown, so it's easy to know when there's a >> configuration problem and how to fix it. On the other, getting no wrap >> is obvious itself, and may be better for users to initially see an >> unwrapped page rather than seeing their applications explode. >> >> I'd expect that there would typically be a catch-all owrap defined >> anyway, so it's unlikely that this will be much of an issue in practice. >> But in retrospect again, I think it's better to fail more gracefully by >> showing an unwrapped view instead of an exception. I'll go ahead and >> make this change too. >> >>> Please forgive the digression, but this is physically sort of tied >>> in: we still need a good way to allow a set of "top level names" to >>> be supplied to templates. So far, the best we could do for that >>> pattern has been something like ("api" is not a good name, I can't >>> think of anything better, though): >> >> Can you give an example use case for this? For the cases in my mind, I'd >> prefer to push as much logic out into the owrap as possible, so that the >> actual views don't need to worry about it. I can potentially see a lot >> more ui reuse if this is possible. For example, I can write management >> views against a dublin core interface, and this can be used in any >> application now because it's not tied to any owrap macro. >> >> The fuzzy area in my mind is a dynamic sidebar. I often have cases where >> there's *always* a sidebar in the theme, maybe save for a couple of >> pages, but the contents change depending on the view. It comes down to >> whether you want to manage the contents of the sidebar as part of the >> view, or part of the owrap, and I think this depends on how drastic the >> changes themselves are. >> >> I think having the owrap do some sort of lookup to figure out what goes >> in the sidebar is more flexible. But in practice, I've found it more >> annoying to work with it this way, because it's more convenient to >> handle it in the view's template/logic, especially if it's varied on a >> view to view basis. >> >> Is this the sort of thing you have in mind? >> >>> class TemplateAPI: >>> def __init__(self, context, request): >>> ... do stuff ... >>> >>> Then in a view: >>> >>> api = TemplateAPI(context, request) >>> return render_template_to_response('templates/mytemplate.pt', >>> api=api) >>> >>> When the template needs access to "common" names, it then does e.g. >>> tal:content="api.something". >> >> I guess I don't exactly follow what the top level common names are. Are >> they things like topnav, header, footer, where those are calculated >> based on context and security? >> >>> Malthe said it might be possible to register one or more new TAL >>> expression types (each of which might represent a namespace) so >>> templates could do something like tal:content="api:something" (note >>> colon instead of dot) to get top-level names instead. The view would >>> no longer need to pass an "api" to provide the template with access >>> to very common top-level names. >> >> I personally like this sort of thing. With zpt in a grok/plone setting, >> I've found myself writing traversal adapters for things like checking >> security, or application wide custom template "filters". It's much >> easier to be able to use these in a template by using this sort of >> syntax rather than passing them on through the view. For example: >> >> <a tal:attributes="href model_url(context, request, 'edit')" >> tal:condition="context/has_permission:edit">Edit</a> >> >> Maybe some sort of syntax for model_url would be convenient too :) >> What do you guys typically do? >> >>> However, computing the values for the top-level names often requires >>> access to stuff in the request or the context, and the current >>> "render_template" APIs don't require that you pass either in to the >>> view. >>> >>> I guess we could provide an alternate implementation of the template* >>> APIs (like render_template_to_response and get_template, etc) that >>> must be passed the request (the request has access to the context too >>> as request.context) as the first argument if values for names needed >>> to be computed based on those bits of information. >> >> That sounds reasonable to me. >> >>> If views had access to top-level names like this, we could also just >>> do owraps the more traditional way (using METAL), if one of the names >>> was e.g. "main_template". I suppose the names would be computed via >>> an adapter lookup just like the rm.owrap stuff does now. >> >> For cases where the owrap varies a lot from view to view, I think the >> metal approach works well. But for times when the dynamicness of the >> owrap can be easily calculated from the owrap, I think pushing it to the >> owrap makes sense. >> >>> That said, I don't think that approach is mutually exclusive with the >>> pagelet approach. The pagelet approach is more generic: any >>> templating language could be used for the owrap or the wrapped view; >>> the same can't be said for the top-level-name way. Maybe some >>> combination of both. >> >> Definitely. Although imho, if you're using macros for the wrapping in >> all your views, then you have less to gain by using an adapted owrap. >> >> Robert >> >>> On 8/24/09 2:14 AM, Robert Marianski wrote: >>>> I was thinking about different ways to apply the owrap theme that's >>>> typical for most applications. >>>> >>>> I like the way that z3c.pagelet does it: >>>> http://svn.zope.org/z3c.pagelet/trunk/ >>>> >>>> To summarize, views are registered through a different directive, and >>>> then a layout is applied with a special directive. The advantage >>>> here is >>>> that the views no longer specify their master template. It's configured >>>> externally through zcml. This, theoretically anyway, allows more view >>>> reuse since they can be registered with a separate owrap in a different >>>> application without modification to the view code. >>>> >>>> Anyway, I have a simple poc implementation for repoze.bfg. >>>> $ svn co http://svn.repoze.org/playground/rmarianski/rm.owrap/trunk/ >>>> rm.owrap >>>> $ cd rm.owrap >>>> $ python bootstrap.py >>>> $ bin/buildout >>>> $ bin/test >>>> $ bin/paster serve src/dummyapp/dummyapp.ini >>>> >>>> Like z3c.pagelet, it adds a new directive for view registration. But >>>> instead of a new directive for the layout, it just uses a plain adapter >>>> to get the owrap. A new directive might be better because it would >>>> stand >>>> out more in the zcml, but it was easier to do this way for a poc. >>>> >>>> Robert >>>> _______________________________________________ >>>> Repoze-dev mailing list >>>> Repoze-dev@lists.repoze.org >>>> http://lists.repoze.org/listinfo/repoze-dev >>>> >>> _______________________________________________ >>> Repoze-dev mailing list >>> Repoze-dev@lists.repoze.org >>> http://lists.repoze.org/listinfo/repoze-dev >> > _______________________________________________ Repoze-dev mailing list Repoze-dev@lists.repoze.org http://lists.repoze.org/listinfo/repoze-dev