[Checkins] SVN: z3c.template/branches/nadako-contexttemplate/ Make a branch for support context-specific templates.
Dan Korostelev
nadako at gmail.com
Wed Feb 25 19:05:00 EST 2009
Log message for revision 97279:
Make a branch for support context-specific templates.
One test in the README.txt mystically fails and I currently don't have any idea why.
Also, I would be glad if someone reviews this addition.
Changed:
A z3c.template/branches/nadako-contexttemplate/
U z3c.template/branches/nadako-contexttemplate/CHANGES.txt
U z3c.template/branches/nadako-contexttemplate/src/z3c/template/README.txt
U z3c.template/branches/nadako-contexttemplate/src/z3c/template/template.py
U z3c.template/branches/nadako-contexttemplate/src/z3c/template/zcml.py
U z3c.template/branches/nadako-contexttemplate/src/z3c/template/zcml.txt
-=-
Modified: z3c.template/branches/nadako-contexttemplate/CHANGES.txt
===================================================================
--- z3c.template/trunk/CHANGES.txt 2009-02-25 23:56:48 UTC (rev 97278)
+++ z3c.template/branches/nadako-contexttemplate/CHANGES.txt 2009-02-26 00:04:59 UTC (rev 97279)
@@ -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/branches/nadako-contexttemplate/src/z3c/template/README.txt
===================================================================
--- z3c.template/trunk/src/z3c/template/README.txt 2009-02-25 23:56:48 UTC (rev 97278)
+++ z3c.template/branches/nadako-contexttemplate/src/z3c/template/README.txt 2009-02-26 00:04:59 UTC (rev 97279)
@@ -412,6 +412,47 @@
<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), IPageTemplate)
+
+First. Let's try to simply get it as a multi-adapter.
+
+ >>> template = zope.component.getMultiAdapter((view, request, content),
+ ... interfaces.IPageTemplate)
+ >>> 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/branches/nadako-contexttemplate/src/z3c/template/template.py
===================================================================
--- z3c.template/trunk/src/z3c/template/template.py 2009-02-25 23:56:48 UTC (rev 97278)
+++ z3c.template/branches/nadako-contexttemplate/src/z3c/template/template.py 2009-02-26 00:04:59 UTC (rev 97279)
@@ -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/branches/nadako-contexttemplate/src/z3c/template/zcml.py
===================================================================
--- z3c.template/trunk/src/z3c/template/zcml.py 2009-02-25 23:56:48 UTC (rev 97278)
+++ z3c.template/branches/nadako-contexttemplate/src/z3c/template/zcml.py 2009-02-26 00:04:59 UTC (rev 97279)
@@ -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/branches/nadako-contexttemplate/src/z3c/template/zcml.txt
===================================================================
--- z3c.template/trunk/src/z3c/template/zcml.txt 2009-02-25 23:56:48 UTC (rev 97278)
+++ z3c.template/branches/nadako-contexttemplate/src/z3c/template/zcml.txt 2009-02-26 00:04:59 UTC (rev 97279)
@@ -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