gpt4 book ai didi

python - CherryPy 以 Cheetah 作为插件 + 工具 - 空白页

转载 作者:行者123 更新时间:2023-12-01 05:08:50 33 4
gpt4 key购买 nike

CherryPy 不断返回空白页或返回我在 Controller 中返回的值。我重写了一个确实有效的 django 和 jinja2 版本,显然这个版本不行,这与前面提到的几乎相同。

我在工具位中做了一些 pprint,它确实用解析的 html 填充了 request.body,但在 Controller 中设置了 pass 时不会输出它。如果我在 Controller 中返回一个以简单“用户”形式显示的 {'user':True}。

通过一些在线示例和 SickBeard 的代码,我得出以下结论:

Controller :

class RootController(object):
@cherrypy.expose
@cherrypy.tools.render(template="page/home.html")
def index(self):
pass

工具:

class CheetahTool(cherrypy.Tool):
def __init__(self):
cherrypy.Tool.__init__(self, 'on_start_resource',
self._render,
priority=30)

def _render(self, template=None, debug=False):
if cherrypy.response.status > 399:
return

# retrieve the data returned by the handler
data = cherrypy.response.body or {}
template = cherrypy.engine.publish("lookup-template", template).pop()

if template and isinstance(data, dict):
for k,v in data:
template.__setattr__(k, v)

# dump the template using the dictionary
if debug:
try:
cherrypy.response.body = unicode(template).encode('utf-8', 'xmlcharrefreplace')
except Exception as e:
from pprint import pprint
pprint(e.message)
else:
cherrypy.response.body = template.respond()

插件:

class PageTemplate(Template):
"""
Thank you SickBeard
"""
def __init__(self, base_dir, template, *args, **KWs):
KWs['file'] = os.path.join(base_dir, template)
super(PageTemplate, self).__init__(*args, **KWs)
application = cherrypy.tree.apps['']
config = application.config
self.sbRoot = base_dir
self.sbHttpPort = config['global']['server.socket_port']
self.sbHttpsPort = self.sbHttpPort
self.sbHttpsEnabled = False
if cherrypy.request.headers['Host'][0] == '[':
self.sbHost = re.match("^\[.*\]", cherrypy.request.headers['Host'], re.X|re.M|re.S).group(0)
else:
self.sbHost = re.match("^[^:]+", cherrypy.request.headers['Host'], re.X|re.M|re.S).group(0)

if "X-Forwarded-Host" in cherrypy.request.headers:
self.sbHost = cherrypy.request.headers['X-Forwarded-Host']
if "X-Forwarded-Port" in cherrypy.request.headers:
self.sbHttpPort = cherrypy.request.headers['X-Forwarded-Port']
self.sbHttpsPort = self.sbHttpPort
if "X-Forwarded-Proto" in cherrypy.request.headers:
self.sbHttpsEnabled = True if cherrypy.request.headers['X-Forwarded-Proto'] == 'https' else False

self.sbPID = str(aquapi.PID)
self.menu = [
{ 'title': 'Home', 'key': 'home' },
{ 'title': 'Users', 'key': 'users' },
{ 'title': 'Config', 'key': 'config' },
]

def render(self):
return unicode(self).encode('utf-8', 'xmlcharrefreplace')


class CheetahTemplatePlugin(plugins.SimplePlugin):
def __init__(self, bus, base_dir=None, base_cache_dir=None,
collection_size=50, encoding='utf-8'):
plugins.SimplePlugin.__init__(self, bus)
self.base_dir = base_dir
self.base_cache_dir = base_cache_dir or tempfile.gettempdir()
self.encoding = encoding
self.collection_size = collection_size

def start(self):
self.bus.log('Setting up Cheetah resources')
self.bus.subscribe("lookup-template", self.get_template)

def stop(self):
self.bus.log('Freeing up Cheetah resources')
self.bus.unsubscribe("lookup-template", self.get_template)
self.lookup = None

def get_template(self, name):
"""
Returns Cheetah's template by name.
"""
return PageTemplate(self.base_dir, name)

初始化:

        # Template engine tool
from aquapi.web.tools.template import CheetahTool
cherrypy.tools.render = CheetahTool()

# Tool to load the logged in user or redirect
# the client to the login page
from aquapi.web.tools.user import UserTool
cherrypy.tools.user = UserTool()


from aquapi.web.controllers import RootController
webapp = RootController()

# Let's mount the application so that CherryPy can serve it
app = cherrypy.tree.mount(webapp, '/', os.path.join(self.base_dir, "app.cfg"))

# Template engine plugin
from aquapi.web.plugin.template import CheetahTemplatePlugin
engine.cheetah = CheetahTemplatePlugin(engine,
os.path.join(self.base_dir, 'aquapi/web/templates'),
os.path.join(self.base_dir, 'cache'))
engine.cheetah.subscribe()

最佳答案

总的来说,对我来说,这是您的代码片段中发生的某种过度设计。 CherryPy 插件通常用于系统任务(例如,在引擎启动时放置 PID 文件,在停止时将其删除)或异步任务(例如,在单独的线程中发送电子邮件)。模板渲染显然与请求处理同步发生,因此我不认为从 CherryPy 工具中提取此逻辑有什么意义。 CherryPy中有一个类,cherrypy._cptools.HandlerWrapperTool ,它演示了包装处理程序返回值的建议方法。

我从未使用过 Cheetah,所以我的示例是基于 Jinja2 的。您只需更改模板引擎实例(更改为 Cheetah)并更正其调用。其余的都是一样的。

#!/usr/bin/env python
# -*- coding: utf-8 -*-


import os
import types

import cherrypy
import jinja2


path = os.path.abspath(os.path.dirname(__file__))
config = {
'global' : {
'server.socket_host' : '127.0.0.1',
'server.socket_port' : 8080,
'server.thread_pool' : 4
}
}


class TemplateTool(cherrypy.Tool):

_engine = None
'''Jinja environment instance'''


def __init__(self):
viewLoader = jinja2.FileSystemLoader(os.path.join(path, 'view'))
self._engine = jinja2.Environment(loader = viewLoader)

cherrypy.Tool.__init__(self, 'before_handler', self.render)

def __call__(self, *args, **kwargs):
if args and isinstance(args[0], (types.FunctionType, types.MethodType)):
# @template
args[0].exposed = True
return cherrypy.Tool.__call__(self, **kwargs)(args[0])
else:
# @template()
def wrap(f):
f.exposed = True
return cherrypy.Tool.__call__(self, *args, **kwargs)(f)
return wrap

def render(self, name = None):
cherrypy.request.config['template'] = name

handler = cherrypy.serving.request.handler
def wrap(*args, **kwargs):
return self._render(handler, *args, **kwargs)
cherrypy.serving.request.handler = wrap

def _render(self, handler, *args, **kwargs):
template = cherrypy.request.config['template']
if not template:
parts = []
if hasattr(handler.callable, '__self__'):
parts.append(handler.callable.__self__.__class__.__name__.lower())
if hasattr(handler.callable, '__name__'):
parts.append(handler.callable.__name__.lower())
template = u'/'.join(parts)

data = handler(*args, **kwargs) or {}
renderer = self._engine.get_template(u'{0}.html'.format(template))

return renderer.render(**data)


cherrypy.tools.template = TemplateTool()


class App:

@cherrypy.expose
def index(self):
'''No renderer applied, CherryPy outputs dict keys'''
return {'user': 123}

@cherrypy.tools.template
def auto(self):
return {'user': 123}

@cherrypy.tools.template(name = 'app/auto')
def manual(self):
return {'user': 234}


if __name__ == '__main__':
cherrypy.quickstart(App(), '/', config)

沿着 python 文件,创建目录 view/app 并将以下内容放入名为 auto.html 的文件中。

<!DOCTYPE html>
<html>
<head>
<meta http-equiv='content-type' content='text/html; charset=utf-8' />
<title>Test</title>
</head>
<body>
<p>User: <em>{{ user }}</em></p>
</body>
</html>

关于 TemplateTool 的一些注释。首先,您可以通过两种方式将其用作装饰器:不进行调用,以及使用模板名称参数进行调用。您可以像配置中的任何其他 CherryPy 工具一样使用该工具(例如,使所有 Controller 方法来渲染模板)。其次,遵循约定优于配置的原则,当未提供模板名称时,该工具将使用classname/methodname.html。第三,装饰器公开了该方法,因此您不需要在顶部添加 @cherrypy.expose

关于python - CherryPy 以 Cheetah 作为插件 + 工具 - 空白页,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24578794/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com