[Checkins] SVN: z3c.template/trunk/ Merge the context template branch.
Dan Korostelev
nadako at gmail.com
Thu Feb 26 09:10:09 EST 2009
Log message for revision 97301:
Merge the context template branch.
Changed:
U z3c.template/trunk/CHANGES.txt
U z3c.template/trunk/src/z3c/template/README.txt
U z3c.template/trunk/src/z3c/template/template.py
U z3c.template/trunk/src/z3c/template/zcml.py
U z3c.template/trunk/src/z3c/template/zcml.txt
-=-
Modified: z3c.template/trunk/CHANGES.txt
===================================================================
--- z3c.template/trunk/CHANGES.txt 2009-02-26 13:58:13 UTC (rev 97300)
+++ z3c.template/trunk/CHANGES.txt 2009-02-26 14:10:08 UTC (rev 97301)
@@ -5,6 +5,12 @@
1.2.0 (unreleased)
------------------
+* Add support for context-specific templates. Now, templates can be
+ registered and looked up using (view, request, context) triple.
+ To do that, pass the ``context`` argument to the ZCML directives.
+ The ``getPageTemplate`` and friends will now try to lookup context
+ specific template first and then fall back to (view, request) lookup.
+
* Allow use of ``z3c.pt`` using ``z3c.ptcompat`` compatibility layer.
* Forward the template kwargs to the options of the macro
Modified: z3c.template/trunk/src/z3c/template/README.txt
===================================================================
--- z3c.template/trunk/src/z3c/template/README.txt 2009-02-26 13:58:13 UTC (rev 97300)
+++ z3c.template/trunk/src/z3c/template/README.txt 2009-02-26 14:10:08 UTC (rev 97301)
@@ -392,9 +392,8 @@
... self.context = context
... self.request = request
-By defining the "template" property as a "RegisteredPageTemplate" a lookup for
-a registered template is done when it is called. Also notice that it is no
-longer necessary to derive the view from BaseView!
+By defining the "template" property as a "getPageTemplate" a lookup for
+a registered template is done when it is called.
>>> simple = UseOfViewTemplate(root, request)
>>> print simple.template()
@@ -402,7 +401,7 @@
Because the demo template was registered for any ("None") interface we see the
demo template when rendering our new view. We register a new template
-especially for the new view. Also not that the "macroTemplate" has been
+especially for the new view. Also note that the "macroTemplate" has been
created earlier in this test.
>>> factory = TemplateFactory(contentTemplate, 'text/html')
@@ -412,6 +411,48 @@
<div>demo content</div>
+Context-specific templates
+--------------------------
+
+The ``TemplateFactory`` can be also used for (view, request, context)
+lookup. It's useful when you want to override a template for specific
+content object or type.
+
+Let's define a sample content type and instantiate a view for it.
+
+ >>> class IContent(zope.interface.Interface):
+ ... pass
+ >>> class Content(object):
+ ... zope.interface.implements(IContent)
+
+ >>> content = Content()
+ >>> view = UseOfViewTemplate(content, request)
+
+Now, let's provide a (view, request, context) adapter using TemplateFactory.
+
+ >>> contextTemplate = os.path.join(temp_dir, 'context.pt')
+ >>> open(contextTemplate, 'w').write('<div>context-specific</div>')
+ >>> factory = TemplateFactory(contextTemplate, 'text/html')
+
+ >>> component.provideAdapter(factory,
+ ... (IUseOfViewTemplate, IDefaultBrowserLayer, IContent),
+ ... interfaces.IContentTemplate)
+
+First. Let's try to simply get it as a multi-adapter.
+
+ >>> template = zope.component.getMultiAdapter((view, request, content),
+ ... interfaces.IContentTemplate)
+ >>> print template(view)
+ <div>context-specific</div>
+
+The ``getPageTemplate`` and friends will try to lookup a context-specific
+template before doing more generic (view, request) lookup, so our view
+should already use our context-specific template:
+
+ >>> print view.template()
+ <div>context-specific</div>
+
+
Use case ``template by interface``
----------------------------------
Modified: z3c.template/trunk/src/z3c/template/template.py
===================================================================
--- z3c.template/trunk/src/z3c/template/template.py 2009-02-26 13:58:13 UTC (rev 97300)
+++ z3c.template/trunk/src/z3c/template/template.py 2009-02-26 14:10:08 UTC (rev 97301)
@@ -45,7 +45,7 @@
self.template = ptcompat.ViewPageTemplateFile(filename,
content_type=contentType)
- def __call__(self, view, request):
+ def __call__(self, view, request, context=None):
if self.macro is None:
return self.template
return Macro(
@@ -76,8 +76,13 @@
self.name = name
def __call__(self, instance, *args, **keywords):
- template = component.getMultiAdapter(
- (instance, instance.request), self.provides, name=self.name)
+ template = component.queryMultiAdapter(
+ (instance, instance.request, instance.context),
+ self.provides, name=self.name)
+ if template is None:
+ template = component.getMultiAdapter(
+ (instance, instance.request),
+ self.provides, name=self.name)
return template(instance, *args, **keywords)
def __get__(self, instance, type):
Modified: z3c.template/trunk/src/z3c/template/zcml.py
===================================================================
--- z3c.template/trunk/src/z3c/template/zcml.py 2009-02-26 13:58:13 UTC (rev 97300)
+++ z3c.template/trunk/src/z3c/template/zcml.py 2009-02-26 14:10:08 UTC (rev 97301)
@@ -74,6 +74,12 @@
default=IDefaultBrowserLayer,
)
+ context = zope.configuration.fields.GlobalObject(
+ title = u'Context',
+ description = u'The context for which the template should be available',
+ required = False,
+ )
+
provides = zope.configuration.fields.GlobalInterface(
title=u"Interface the template provides",
description=u"This attribute specifies the interface the template"
@@ -106,7 +112,7 @@
_context, template, name=u'',
for_=zope.interface.Interface, layer=IDefaultBrowserLayer,
provides=z3c.template.interfaces.IContentTemplate,
- contentType='text/html', macro=None):
+ contentType='text/html', macro=None, context=None):
# Make sure that the template exists
template = os.path.abspath(str(_context.path(template)))
@@ -116,20 +122,25 @@
factory = TemplateFactory(template, contentType, macro)
zope.interface.directlyProvides(factory, provides)
+ if context is not None:
+ for_ = (for_, layer, context)
+ else:
+ for_ = (for_, layer)
+
# register the template
if name:
zope.component.zcml.adapter(_context, (factory,), provides,
- (for_, layer), name=name)
+ for_, name=name)
else:
zope.component.zcml.adapter(_context, (factory,), provides,
- (for_, layer))
+ for_)
def layoutTemplateDirective(
_context, template, name=u'',
for_=zope.interface.Interface, layer=IDefaultBrowserLayer,
provides=z3c.template.interfaces.ILayoutTemplate,
- contentType='text/html', macro=None):
+ contentType='text/html', macro=None, context=None):
templateDirective(_context, template, name, for_, layer, provides,
- contentType, macro)
+ contentType, macro, context)
Modified: z3c.template/trunk/src/z3c/template/zcml.txt
===================================================================
--- z3c.template/trunk/src/z3c/template/zcml.txt 2009-02-26 13:58:13 UTC (rev 97300)
+++ z3c.template/trunk/src/z3c/template/zcml.txt 2009-02-26 14:10:08 UTC (rev 97301)
@@ -109,6 +109,72 @@
<div>layout</div>
+Context-specific template
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Most of views have some object as their context and it's ofter very
+useful to be able register context-specific template. We can do that
+using the ``context`` argument of the ZCML directive.
+
+Let's define some content type:
+
+ >>> class IContent(zope.interface.Interface):
+ ... pass
+ >>> class Content(object):
+ ... zope.interface.implements(IContent)
+
+ >>> sys.modules['custom'].IContent = IContent
+
+Now, we can register a template for this class. Let's create one and
+register:
+
+ >>> file = os.path.join(temp_dir, 'context.pt')
+ >>> open(file, 'w').write('''<div>i'm context-specific</div>''')
+
+ >>> context = xmlconfig.string("""
+ ... <configure
+ ... xmlns:z3c="http://namespaces.zope.org/z3c">
+ ... <z3c:template
+ ... template="%s"
+ ... for="custom.IView"
+ ... context="custom.IContent"
+ ... />
+ ... </configure>
+ ... """ % file, context=context)
+
+We can now lookup it using the (view, request, context) discriminator:
+
+ >>> content = Content()
+ >>> view = View(content, request)
+
+ >>> template = zope.component.queryMultiAdapter((view, request, content),
+ ... interface=IContentTemplate)
+
+ >>> print template(view)
+ <div>i'm context-specific</div>
+
+The same will work with layout registration directive:
+
+ >>> file = os.path.join(temp_dir, 'context_layout.pt')
+ >>> open(file, 'w').write('''<div>context-specific layout</div>''')
+ >>> context = xmlconfig.string("""
+ ... <configure
+ ... xmlns:z3c="http://namespaces.zope.org/z3c">
+ ... <z3c:layout
+ ... template="%s"
+ ... for="custom.IView"
+ ... context="custom.IContent"
+ ... />
+ ... </configure>
+ ... """ % file, context=context)
+
+ >>> layout = zope.component.queryMultiAdapter((view, request, content),
+ ... interface=ILayoutTemplate)
+
+ >>> print layout(view)
+ <div>context-specific layout</div>
+
+
Named template
--------------
More information about the Checkins
mailing list