So I am taking my first steps with repoze.bfg.
- I am posting this to both: repoze-dev and genshi:
the problem described is more repoze.bfg specific, but I am hoping to
get some feedback concerning the general idea from genshi users, too.

I prefer genshi over zpt templates, and - maybe somehow unusual 
- wanted to use them in a contentprovider / viewlet style.

I know there are other possibilities to work with templates in pure
genshi, for the most part I have been using the style suggested in

  http://genshi.edgewall.org/wiki/GenshiRecipes/PyLayoutEquivalent

(i. e. I filled a layout template, included with xi:include at the bottom)

And I am aware that for repoze.bfg there are some others ways suggested in
the docs (zpt+xml):
 
  http://static.repoze.org/bfgdocs/api/template.html
  http://static.repoze.org/bfgdocs/#tutorials (steps 3+4)

and that Chris, although the author of repoze.bfg.viewgroup
is not to much in favor of this contentprovider / viewlet style
  
  http://www.plope.com/Members/chrism/repoze.bfg.viewgroup-1
  http://svn.repoze.org/repoze.bfg.viewgroup/trunk/README.txt

Still I like the idea of contentprovider / viewlets and I tried this
with genshi. I got something running, but only with the original
genshi, not the the chameleon.genshi package provided with repoze.bfg, 
I will explain:

For example the navigation of any of my pages is just a html snippet
(needs the genshi namespace to be rendered by genshi)

-------------------- templates/nav.html --------------------
<div xmlns:py="http://genshi.edgewall.org/";
     py:strip=""
     >
  <a href="home">Home</a>
  <a href="bla">Bla</a>
</div>
------------------------------------------------------------

in my models.py I then have an interface and a class for the
navigation

  class INav(Interface):
      pass

  class Nav(object):
      implements(INav)
      tmplt="templates/nav.html"

and I can easily use this Navigation in some other
similar blocks - for example it is used
here in a Content block (besides another block: main)


  class IContent(Interface):
      pass

  class Content(object):
      implements(IContent)
      tmplt="templates/content.html"
      nav=Nav()
      main=MainA()

(similar code for IMain/main=MainA())

The content template then references the nav and the main
parts:

-------------------- templates/content.html --------------------
<div  xmlns:py="http://genshi.edgewall.org/";
      py:strip=""
      >

  this is from the content
      
  <div py:replace="Markup(provider('nav'))" />
    
  <div py:replace="Markup(provider('main'))" />
    
  </div>

</div>
----------------------------------------------------------------

Note that I had to use Markup() here, because provider('nav') and
provider('main') are already rendered. I could find Markup() in the
original genshi.core package, but not in the chameleon.genshi
implementation. I am wondering, if Markup() could be added to
chameleon.genshi - or why chameleon.genshi was used in the first place
instead of the original genshi?

My views.py then looks like this:


  # genshi installed with easy_install... in my virtualenv 
  from genshi.template import TemplateLoader
  from genshi.core import Markup

  # could not use this
  # from repoze.bfg.chameleon_genshi import get_template

  from webob import Response


  def my_genshi_render_template_to_response(tmpltfile, **kw):
      loader = TemplateLoader(['./myproject'])
      t=loader.load(tmpltfile)
      d={'Markup': Markup, }
      d.update(kw)
      stream = apply(t.generate, [], d)
      return Response(stream.render('xhtml',
                                    # encoding='utf-8', # default
                                    # doctype=XHTML11
                                    ))


  from repoze.bfg.viewgroup.group import Provider


  @bfg_view(name='nav', request_type=IRequest, for_=IContent,) 
  def nav_view(context, request):
      # print "in nav_view"
      nav=context.nav
      if hasattr(nav, 'tmplt'):
          return my_genshi_render_template_to_response(nav.tmplt)
      else:
          # some default...
          pass


  @bfg_view(name='main', request_type=IRequest, for_=IContent)
  def main_view(context, request):
      main=context.main
      # print main
      if hasattr(main, 'tmplt'):
          return my_genshi_render_template_to_response(main.tmplt)    
      else:
          pass

and so on, in the content_view (for IPage) the content
(including main and nav) is provided to the template

  @bfg_view(name='content', request_type=IRequest, for_=IPage)
  def content_view(context, request):
      content=context.content
      provider=Provider(content, request)
      if hasattr(content, 'tmplt'):
          return my_genshi_render_template_to_response(content.tmplt,
                                                       provider=provider)


So I had to define my own my_genshi_render_template_to_response()
function. For templates with utf-8 text I even had to use

  def MyMarkup(s):
      return Markup(s.decode('utf-8'))

and then fill the dictionnary above accordingly

  d={'Markup': MyMarkup,}

What do you think?

-Andreas
_______________________________________________
Repoze-dev mailing list
Repoze-dev@lists.repoze.org
http://lists.repoze.org/listinfo/repoze-dev

Reply via email to