【问题标题】:Using Jinja2 with CherryPy 3.2将 Jinja2 与 CherryPy 3.2 一起使用
【发布时间】:2012-05-26 10:56:46
【问题描述】:

我通过 mod_wsgi 用 Apache 设置了 Python 3.2。我有 CherryPy 3.2 提供一个简单的“Hello World”网页。在构建网站时,我想开始使用 Jinja2 进行模板化。我是 Python 新手,因此对 Python、CherryPy 或 Jinja 了解不多。

使用下面的代码,我可以加载站点根目录 (/) 和产品页面 (/products) 及其基本文本。这至少让我知道我已经正确设置了 Python、mod_wsgi 和 CherryPy。

因为该站点将有很多页面,所以我想以一种无需在每个页面处理程序类中声明和呈现模板的方式来实现 Jinja 模板。据我所知,最好的方法是包装 PageHandler,类似于以下示例:

我已经实现了第二个示例中的代码,但它并没有改变任何东西。

[代码后的更多细节]

wsgi_handler.py - 一些教程和示例的混搭

import sys, os
abspath = os.path.dirname(__file__)
sys.path.append(abspath)
sys.path.append(abspath + '/libs')
sys.path.append(abspath + '/app')
sys.stdout = sys.stderr

import atexit
import threading
import cherrypy
from cherrypy._cptools import HandlerWrapperTool
from libs.jinja2 import Environment, PackageLoader

# Import from custom module
from core import Page, Products

cherrypy.config.update({'environment': 'embedded'})

env = Environment(loader=PackageLoader('app', 'templates'))

# This should wrap the PageHandler
def interpolator(next_handler, *args, **kwargs):
    template = env.get_template('base.html')
    response_dict = next_handler(*args, **kwargs)
    return template.render(**response_dict)

# Put the wrapper in place(?)
cherrypy.tools.jinja = HandlerWrapperTool(interpolator)

# Configure site routing
root = Page()
root.products = Products()

# Load the application
application = cherrypy.Application(root, '', abspath + '/app/config')

/app/config

[/]
request.dispatch: cherrypy.dispatch.MethodDispatcher()

核心模块类

class Page:
    exposed = True

    def GET(self):
        return "got Page"

    def POST(self, name, password):
        return "created"

class Products:
    exposed = True

    def GET(self):
        return "got Products"

    def POST(self, name, password):
        return "created"

根据我在Google Group 上阅读的内容,我认为我可能需要“打开”Jinja 工具,因此我将配置更新为:

/app/config

[/]
tools.jinja.on = True
request.dispatch: cherrypy.dispatch.MethodDispatcher()

更新配置后,站点根目录和产品页面显示 CherryPy 生成的错误页面“500 Internal Server Error”。在日志中没有找到详细的错误消息(至少在我知道的日志中没有)。

除非它是预先安装的,否则我知道我可能需要现有的Jinja Tool,但我不知道将它放在哪里或如何启用它。我该怎么做?

我这样做是正确的,还是有更好的方法?

编辑(2012 年 5 月 21 日):

这是我正在使用的 Jinja2 模板:

<!DOCTYPE html>
<html>
    <head>
        <title>{{ title }}</title>
    </head>
    <body>
        <h1>Hello World</h1>
    </body>
</html>

【问题讨论】:

    标签: python-3.x cherrypy jinja2


    【解决方案1】:

    我想通了。

    interpolator 函数中,next_handler 函数调用原始的PageHandler(在本例中为Page.GETProducts.GET)。当interpolator 函数将响应视为python dict(字典)时,那些原始PageHandlers 返回字符串,因此当它传递给template.render 时,双星号为**response_dict

    Jinja 模板有一个title 的占位符,因此需要定义一个标题。将纯字符串传递给渲染函数并没有定义标题应该是什么。我们需要将一个实际的 dict 传递给渲染函数(或者什么都不传递,但这有什么好处呢?)。

    注意:对于这些修复中的任何一个,都需要启用 jinja 工具,如问题所示,在配置中将 tools.jinja.on 设置为 True。

    快速修复

    在调用渲染函数时定义标题。为此,我需要更改这一行:

    return template.render(**response_dict) # passing the string as dict - bad
    

    到这里:

    return template.render(title=response_dict) # pass as string and assign to title
    

    像这样,模板以我的 PageHandler 文本作为页面标题呈现。

    更好的修复

    由于模板将变得更加复杂,因此一个渲染函数可能无法始终正确分配必要的占位符。让原始页面处理程序返回一个实际的 dict 并分配模板的许多占位符可能是个好主意。

    保持插值函数不变:

    def interpolator(next_handler, *args, **kwargs):
        template = env.get_template('base.html')
        response_dict = next_handler(*args, **kwargs)
        return template.render(**response_dict)
    

    更新页面和产品以返回定义模板占位符值的实际字典:

    class Page:
        exposed = True
    
        def GET(self):
            dict = {'title' : "got Page"}
            return dict
    
        def POST(self, name, password):
            # This should be updated too
            # I just haven't used it yet
            return "created"
    
    class Products:
        exposed = True
    
        def GET(self):
            dict = {'title' : "got Products"}
            return dict
    
        def POST(self, name, password):
            # This should be updated too
            # I just haven't used it yet
            return "created"
    

    像这样,模板以我的 PageHandler 标题文本作为页面标题呈现。

    【讨论】:

      【解决方案2】:

      还有一个更新的Jinja2 工具,可以在repository 上找到社区贡献的各种食谱。

      【讨论】:

      • 感谢您与我分享。一旦我更熟悉 CherryPy 以及工具的工作原理,我可能会试一试。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-01-02
      • 2017-12-23
      • 1970-01-01
      • 2010-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多