summaryrefslogtreecommitdiff
path: root/repoze
diff options
context:
space:
mode:
authorChris McDonough <chrism@agendaless.com>2009-09-14 07:55:36 +0000
committerChris McDonough <chrism@agendaless.com>2009-09-14 07:55:36 +0000
commit4eb45e9de657bedeb0b03469781c35758500dfa2 (patch)
tree0d4a7b93f08248425af04dcc38d447c1e25e66ad /repoze
parent7dbf3ffc6e3d27dbebe3b32ff6d4c97f6a81de92 (diff)
downloadpyramid-4eb45e9de657bedeb0b03469781c35758500dfa2.tar.gz
pyramid-4eb45e9de657bedeb0b03469781c35758500dfa2.tar.bz2
pyramid-4eb45e9de657bedeb0b03469781c35758500dfa2.zip
- A ZCML ``view`` directive (and the associated ``bfg_view``
decorator) can now accept a "wrapper" value. If a "wrapper" value is supplied, it is the value of a separate view's *name* attribute. When a view with a ``wrapper`` attribute is rendered, the "inner" view is first rendered normally. Its body is then attached to the request as "wrapped_body", and then a wrapper view name is looked up and rendered (using ``repoze.bfg.render_view_to_response``), passed the request and the context. The wrapper view is assumed to do something sensible with ``request.wrapped_body``, usually inserting its structure into some other rendered template. This feature makes it possible to specify (potentially nested) "owrap" relationships between views using only ZCML or decorators (as opposed always using ZPT METAL and analogues to wrap view renderings in outer wrappers).
Diffstat (limited to 'repoze')
-rw-r--r--repoze/bfg/tests/test_zcml.py18
-rw-r--r--repoze/bfg/zcml.py27
2 files changed, 41 insertions, 4 deletions
diff --git a/repoze/bfg/tests/test_zcml.py b/repoze/bfg/tests/test_zcml.py
index e54bd108f..398159801 100644
--- a/repoze/bfg/tests/test_zcml.py
+++ b/repoze/bfg/tests/test_zcml.py
@@ -1321,6 +1321,24 @@ class TestDeriveView(unittest.TestCase):
self.assertEqual(next, True)
self.assertEqual(predicates, [True, True])
+ def test_view_with_wrapper_viewname(self):
+ from webob import Response
+ from zope.component import getSiteManager
+ from repoze.bfg.interfaces import IView
+ def inner_view(context, request):
+ return Response('OK')
+ def outer_view(context, request):
+ return Response('outer ' + request.wrapped_body)
+ sm = getSiteManager()
+ sm.registerAdapter(outer_view, (None, None), IView, 'owrap')
+ result = self._callFUT(inner_view, wrapper_viewname='owrap')
+ self.failIf(result is inner_view)
+ self.assertEqual(inner_view.__module__, result.__module__)
+ self.assertEqual(inner_view.__doc__, result.__doc__)
+ request = DummyRequest()
+ response = result(None, request)
+ self.assertEqual(response.body, 'outer OK')
+
class TestConnectRouteFunction(unittest.TestCase):
def setUp(self):
cleanUp()
diff --git a/repoze/bfg/zcml.py b/repoze/bfg/zcml.py
index 3a2a24819..657105e34 100644
--- a/repoze/bfg/zcml.py
+++ b/repoze/bfg/zcml.py
@@ -58,7 +58,7 @@ from repoze.bfg.view import NotFound
from repoze.bfg.view import MultiView
from repoze.bfg.view import map_view
from repoze.bfg.view import decorate_view
-
+from repoze.bfg.view import render_view_to_response
import martian
@@ -84,6 +84,7 @@ def view(
containment=None,
attr=None,
template=None,
+ wrapper=None,
cacheable=True, # not used, here for b/w compat < 0.8
):
@@ -174,7 +175,8 @@ def view(
template = '%s:%s' % (package_name(_context.resolve('.')), template)
def register():
- derived_view = derive_view(view, permission, predicates, attr, template)
+ derived_view = derive_view(view, permission, predicates, attr, template,
+ wrapper)
r_for_ = for_
r_request_type = request_type
if r_for_ is None:
@@ -244,13 +246,25 @@ def forbidden(_context, view):
view_utility(_context, view, IForbiddenView)
def derive_view(original_view, permission=None, predicates=(), attr=None,
- template=None):
+ template=None, wrapper_viewname=None):
mapped_view = map_view(original_view, attr, template)
- secured_view = secure_view(mapped_view, permission)
+ owrapped_view = owrap_view(mapped_view, wrapper_viewname)
+ secured_view = secure_view(owrapped_view, permission)
debug_view = authdebug_view(secured_view, permission)
derived_view = predicate_wrap(debug_view, predicates)
return derived_view
+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)
+ decorate_view(_owrapped_view, view)
+ return _owrapped_view
+
def predicate_wrap(view, predicates):
if not predicates:
return view
@@ -627,6 +641,11 @@ class IViewDirective(Interface):
description=u'',
required=False)
+ wrapper = TextLine(
+ title = u'The *name* of the view that acts as a wrapper for this view.',
+ description = u'',
+ required=False)
+
request_type = TextLine(
title=u"The request type string or dotted name interface for the view",
description=(u"The view will be called if the interface represented by "