[Checkins] SVN: grok/branches/regebro-guido-templates/
Documentation, plus simplifications spurred on by the documentation.
Lennart Regebro
regebro at gmail.com
Fri Oct 5 17:34:44 EDT 2007
Log message for revision 80670:
Documentation, plus simplifications spurred on by the documentation.
Changed:
U grok/branches/regebro-guido-templates/CHANGES.txt
U grok/branches/regebro-guido-templates/CREDITS.txt
A grok/branches/regebro-guido-templates/doc/minitutorials/template-languages.txt
U grok/branches/regebro-guido-templates/src/grok/components.py
U grok/branches/regebro-guido-templates/src/grok/interfaces.py
-=-
Modified: grok/branches/regebro-guido-templates/CHANGES.txt
===================================================================
--- grok/branches/regebro-guido-templates/CHANGES.txt 2007-10-05 21:34:41 UTC (rev 80669)
+++ grok/branches/regebro-guido-templates/CHANGES.txt 2007-10-05 21:34:44 UTC (rev 80670)
@@ -48,7 +48,7 @@
- The View is now completely template-language agnostic, which makes it
easy to hook in new page template languages.
- - There are now new interfaces (ITemplateFile and ITemplateFileFactory)
+ - There are now new interfaces (ITemplate and ITemplateFileFactory)
used when you implement support for a new templating language.
* The <grok:grok /> ZCML directive now emits a configuration action
Modified: grok/branches/regebro-guido-templates/CREDITS.txt
===================================================================
--- grok/branches/regebro-guido-templates/CREDITS.txt 2007-10-05 21:34:41 UTC (rev 80669)
+++ grok/branches/regebro-guido-templates/CREDITS.txt 2007-10-05 21:34:44 UTC (rev 80670)
@@ -29,6 +29,10 @@
* Kevin M. Smith (skins and layers support)
+* Lennart Regebro (template pluggablility)
+
+* Guido Westdorp (template pluggablility)
+
* ME GROK (team mascot)
Thank you
Added: grok/branches/regebro-guido-templates/doc/minitutorials/template-languages.txt
===================================================================
--- grok/branches/regebro-guido-templates/doc/minitutorials/template-languages.txt (rev 0)
+++ grok/branches/regebro-guido-templates/doc/minitutorials/template-languages.txt 2007-10-05 21:34:44 UTC (rev 80670)
@@ -0,0 +1,147 @@
+==================================
+Plugging in new template languages
+==================================
+
+:Author: Lennart Regebro
+
+Introduction
+------------
+Grok uses the same Zope Page Templates as default templating language, since
+this is the default of Zope 3. Of course you can use whatever templating
+language you want in Grok, but to get the automatic association between
+template objects/files and views you need to do a little bit of extra work.
+
+Inline templates
+----------------
+"Inline" templates are templates where the template code is written inside the
+python class. To get the automatic association to a view class, you need to
+write a class that subclasses from grok.components.GrokPageTemplate, so it
+will be picked up by the template grokkers. It also needs to implement
+grok.interfaces.ITemplateFile. Here is an example:
+
+.. code-block:: python
+
+ class MyPageTemplate(grok.components.GrokPageTemplate):
+
+ def __init__(self, html):
+ self._template = MyTemplate(html)
+ self.__grok_module__ = martian.util.caller_module()
+
+ def _factory_init(self, factory):
+ pass
+
+ def default_namespace(self):
+ return {}
+
+ def render_template(self, view):
+ namespace = self.getDefaultVariables()
+ namespace.update(view.getTemplateVariables())
+ return self._template.render(**namespace)
+
+In the __init__ method of a typical template you pass in what should be
+rendered. This is usually HTML, but can equally well be XML or text, or
+whatever your template renders. Note the line setting self.__grok_module__.
+This is necessary to support inline templates.
+
+The _factory_init method is a call made when setting up views (when the server
+starts). Basically, you can here initialize the view in ways needed to your
+template language. For example, Zope Page Templates set the macro attribute on
+the view class, so that you can access ZPT macros with the standard syntax of
+"context/@@viewname/macros/themacro". Most likely your class doesn't need to
+do anything here.
+
+The default_namespace method should return a dictionary with variables that
+should be included in the namespace that is specific for your template
+language. By default 'context', 'view', 'request' and 'static' is made
+available by the view. Your language might want to use some more.
+
+Lastly, the render_template is the method normally used to render a template
+attached to a view. Here you do whatever necessary to render your template.
+This is usually to call view.default_namespace() and then update the namespace
+with the result of the view-specific "extra_namespace", to let the view add
+more variables to the namespace, and also override the defaults. The above
+example is a reasonable startingpoint for most cases.
+
+With this class finished you can create an inline template, like this:
+
+.. code-block:: python
+
+ class AView(grok.View):
+ pass
+
+ aview = MyPageTemplate('<html><body>Some text</body></html>')
+
+
+File templates
+--------------
+Mostly you want your templates to reside on disk. To do this you need a
+file template class. It looks and works as the template class above, except
+that it loads the template from a file instead:
+
+.. code-block:: python
+
+ class MyPageTemplateFile(grok.components.GrokPageTemplate):
+
+ def __init__(self, filename, _prefix=None):
+ file = open(os.path.join(_prefix, filename)
+ self._template = MyTemplate(file.read())
+ self.__grok_module__ = martian.util.caller_module()
+
+ def render_template(self, view):
+ namespace = self.getDefaultVariables()
+ namespace.update(view.getTemplateVariables())
+ return self._template.render(**namespace)
+
+Here _factory_init and default_namespace is left out, as GrokPaeTemplate
+alredy has them as defaults. The __init__ now takes two parameters, filename
+and _prefix, which is the directory in which the file resides. Although there
+is no requirement that these are the parameters used it is a good idea, since
+that makes the next step easier.
+
+Now you can use this filebase template:
+
+.. code-block:: python
+
+ class AView(grok.View):
+ pass
+
+ aview = MyTemplateFile('lasceuax.html', '.')
+
+
+Templates in the _templates directory
+-------------------------------------
+
+The most common usecase is however to place the templates in the views
+template directory. To do that, a global utility that generates
+MyPageTemplates from the filenames found is needed. That utility needs to
+implement the ITemplateFileFactory interface. The easiest way of doing this is
+to let your template file class implement it directly, by having the above
+filename and _prefix parameters in the __init__ call and tell the component
+architecture that the class provides the interface with a classProvides call.
+You also need to tell Grok that the class should be a direct global utility by
+subclassing from grok.GlobalUtility, and annotating it with a grok.direct()
+annotation. Lastly you need to choose an extension for your template files,
+and set the grok.name to that extension:
+
+ class MyPageTemplateFile(grok.components.GrokPageTemplate):
+
+ zope.interface.implements(grok.interfaces.ITemplateFile)
+ zope.interface.classProvides(grok.interfaces.ITemplateFileFactory)
+ grok.name('mtl')
+ grok.direct()
+
+ def __init__(self, filename, _prefix=None):
+ file = open(os.path.join(_prefix, filename)
+ self._template = MyTemplate(file.read())
+ self.__grok_module__ = martian.util.caller_module()
+
+ def render_template(self, view):
+ namespace = self.getDefaultVariables()
+ namespace.update(view.getTemplateVariables())
+ return self._template.render(**namespace)
+
+When your module gets grokked, Grok will now pick up on the MyPageTemplateFile
+class, register it as a global utility for templates with the '.mtl' extension
+and you can start creating .mtl files in the template directory for your class.
+
+Have fun!
Property changes on: grok/branches/regebro-guido-templates/doc/minitutorials/template-languages.txt
___________________________________________________________________
Name: svn:keywords
+ Id
Modified: grok/branches/regebro-guido-templates/src/grok/components.py
===================================================================
--- grok/branches/regebro-guido-templates/src/grok/components.py 2007-10-05 21:34:41 UTC (rev 80669)
+++ grok/branches/regebro-guido-templates/src/grok/components.py 2007-10-05 21:34:44 UTC (rev 80670)
@@ -124,18 +124,19 @@
def _render_template(self):
return self.template.render_template(self)
- def getDefaultVariables(self):
- # XXX Martijn wants this to be on a template language specific utility. /regebro
+ def default_namespace(self):
namespace = {}
namespace['request'] = self.request
namespace['view'] = self
namespace['context'] = self.context
# XXX need to check whether we really want to put None here if missing
namespace['static'] = self.static
- namespace.update(self.template.getDefaultVariables())
+
+ # Get template langage specific defaults:
+ namespace.update(self.template.default_namespace())
return namespace
- def getTemplateVariables(self):
+ def extra_namespace(self):
return {}
def __getitem__(self, key):
@@ -214,7 +215,13 @@
self.__grok_name__ = name
self.__grok_location__ = location
+ def _factory_init(self, factory):
+ pass
+ def default_namespace(self):
+ return {}
+
+
class PageTemplate(GrokPageTemplate, TrustedAppPT, pagetemplate.PageTemplate):
expand = 0
@@ -234,15 +241,15 @@
def _factory_init(self, factory):
factory.macros = self.macros
- def getDefaultVariables(self):
- return {}
-
+ def default_namespace(self):
+ return self.pt_getContext()
+
def render_template(self, view):
- namespace = self.pt_getContext()
- namespace.update(view.getDefaultVariables())
+ namespace = view.default_namespace()
+ namespace.update(view.extra_namespace())
return self.pt_render(namespace)
-
+
class PageTemplateFile(GrokPageTemplate, TrustedAppPT,
pagetemplatefile.PageTemplateFile):
@@ -261,12 +268,12 @@
def _factory_init(self, factory):
factory.macros = self.macros
- def getDefaultVariables(self):
- return {}
-
+ def default_namespace(self):
+ return self.pt_getContext()
+
def render_template(self, view):
- namespace = self.pt_getContext()
- namespace.update(view.getDefaultVariables())
+ namespace = view.default_namespace()
+ namespace.update(view.extra_namespace())
return self.pt_render(namespace)
Modified: grok/branches/regebro-guido-templates/src/grok/interfaces.py
===================================================================
--- grok/branches/regebro-guido-templates/src/grok/interfaces.py 2007-10-05 21:34:41 UTC (rev 80669)
+++ grok/branches/regebro-guido-templates/src/grok/interfaces.py 2007-10-05 21:34:44 UTC (rev 80670)
@@ -444,13 +444,10 @@
"""Template objects created from files
"""
- def __call__(args, request):
- """Renders the template. Args is a tuple of arguments."""
-
def _factory_init(factory):
"""Template language specific initializations on the view factory."""
- def getDefaultVariables():
+ def default_namespace():
"""Returns a dictionary of template language specific variables."""
def render_template(view):
More information about the Checkins
mailing list