[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