Edgewall Software

Version 2 (modified by Pedro Algarvio, aka, s0undt3ch <ufs@…>, 17 years ago) (diff)

typo

Genshi Recipes: Using Genshi with Pylons

To use Genshi with Pylons you need to make some aditional steps, which is what's going to be explained here.

Adding Genshi Template Engine

First you need some changes in your application's middleware.py.

Genshi only

    # Load our Pylons configuration defaults
    config = load_environment()
    config.init_app(global_conf, app_conf, package='<appname>')

    # Setup Genshi(only) Template Engine
    config.template_engines = []
    config.add_template_engine('genshi', '<appname>.templates', {})

Genshi and Myghty

    # Load our Pylons configuration defaults
    config = load_environment()
    config.init_app(global_conf, app_conf, package='<appname>')

    # Setup Genshi Template Engine
   myghty = config.template_engines.pop()
   config.add_template_engine('genshi', '<appname>.templates', {})
   config.template_engines.append(myghty)

WebHelpers and Genshi

To use WebHelpers within a Genshi template, the helper return values need to be wrapped in a Markup object, as it would otherwise be escaped.

The Hard Way

You can do for example(I won't explain the template, for that consult the Genshi Guide):

<!DOCTYPE html
    PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:py="http://genshi.edgewall.org/"
      xmlns:xi="http://www.w3.org/2001/XInclude"
      py:strip="">
<head py:match="head">
  <title>The Title</title>
  <body>
     <h1>hello</h1>
     ${XML(h.<helper>)}
  </body>
</html>

...but the above becomes quite painfull when using several WebHelpers.

The Easy Way

The solution is to wrap all helper functions into Markup objects. For that, edit <appname>/lib/helpers.py and add:

from genshi.core import Markup

def wrap_helpers(localdict):
    def helper_wrapper(func):
        def wrapped_helper(*args, **kw):
            return Markup(func(*args, **kw))
        wrapped_helper.__name__ = func.__name__
        return wrapped_helper
    for name, func in localdict.iteritems():
        if not callable(func) or not func.__module__.startswith('webhelpers.rails'):
            continue
        localdict[name] = helper_wrapper(func)
wrap_helpers(locals())

Now edit <appname>/config/middleware.py and just add:

from <appname>.lib import helpers

The above will cause all helpers to be wrapped uppon application initialization.

Now you can use the WebHelpers? like you used to with Myghty, for example:

<!DOCTYPE html
    PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:py="http://genshi.edgewall.org/"
      xmlns:xi="http://www.w3.org/2001/XInclude"
      py:strip="">
<head py:match="head">
  <title>The Title</title>
  <body>
     <h1>hello</h1>
     ${h.<helper>}
  </body>
</html>

Final Thoughts

You might also think about adding to <appname>/lib/helpers.py:

from genshi.builder import tag

The Genshi tag object is just like the content_tag() WebHelper, but it will be faster since it does not have to pass trough the wrapper.

And that's all....