python - Flask 可以提供 CherryPy 风格的路由吗?

标签 python flask cherrypy

默认的 CherryPy 路由样式基于具有 @cherrypy.expose 修饰的方法的类的实例。

在下面的示例中,这些 url 是通过对其他普通类进行简单调整而提供的。

/
/hello
/hello/again
/bye
/bye/again

我想知道是否有办法使用 Flask 的@route 或其他一些装饰器来实现这一点。

import cherrypy

class Root(object):
    @cherrypy.expose
    def index(self):
        return 'my app'

class Greeting(object):
    def __init__(self, name, greeting):
        self.name = name
        self.greeting = greeting

    @cherrypy.expose
    def index(self):
        return '%s %s!' %(self.greeting, self.name)

    @cherrypy.expose
    def again(self):
        return '%s again, %s!' %(self.greeting, self.name)

if __name__ == '__main__':
    root = Root()
    root.hello = Greeting('Foo', 'Hello')
    root.bye = Greeting('Bar', 'Bye')
    cherrypy.quickstart(root)

最佳答案

为了做这样的事情,你必须使用一些 python 魔法,但是,使用 flask 绝对可以做到。复制您的示例的最直接方法是子类 flask 。这是一种方法:

import inspect
from flask import Flask


def expose(f):
    """Decorator that flags a method to be exposed"""
    f._exposed_method = True
    return f


class FlaskOfCherryPy(Flask):
    """Custom flask that allows cherrypy's expose decorator"""
    def quickstart(self, root_handler, *args, **kwargs):
        self._process_root_handler(root_handler)
        self.run(*args, **kwargs)

    def _process_root_handler(self, root_handler):
        # Prime the recursive processing
        root_url = []
        self._process_a_handler(root_handler, root_url)

    def _process_a_handler(self, current_handler, url_stack):
        # This gives a list of all the members of current_handler
        members = inspect.getmembers(current_handler)
        for name, value in members:
            # You probably want to skip things that start with a _ or __
            if name.startswith('_'):
                continue

            # Check if the method is decorated
            is_exposed_method = getattr(value, '_exposed_method', False)

            # If it's a callable with the _exposed_method attribute set
            # Then it's an exposed method
            if is_exposed_method and callable(value):
                self._add_exposed_url(url_stack, name, value)
            else:
                new_stack = url_stack[:]
                new_stack.append(name)
                self._process_a_handler(value, new_stack)

    def _add_exposed_url(self, url_stack, name, view_func):
        copied_stack = url_stack[:]

        if name != 'index':
            copied_stack.append(name)

        url = "/%s" % "/".join(copied_stack)

        if name == 'index':
            copied_stack.append(name)

        view_name = "_".join(copied_stack)
        self.add_url_rule(url, view_name, view_func)


class Root(object):
    @expose
    def index(self):
        return 'my app'


class Greeting(object):
    def __init__(self, name, greeting):
        self.name = name
        self.greeting = greeting

    @expose
    def index(self):
        return '%s %s!' %(self.greeting, self.name)

    @expose
    def again(self):
        return '%s again, %s!' %(self.greeting, self.name)


if __name__ == '__main__':
    root = Root()
    root.hello = Greeting('Foo', 'Hello')
    root.bye = Greeting('Bar', 'Bye')
    app = FlaskOfCherryPy(__name__)
    app.quickstart(root)

本质上,诀窍是获取所有标有 _exposed_method 属性并将它们传递给 Flask.add_url_rule (see docs here)。 Flask 的美妙之处在于它是一个轻量级的系统 扩展它并不是很可怕。我强烈建议你自己潜入 试一试,但我很乐意解决你的问题,所以我的脚本是 a gist here .

我写的这个特定代码并不完美,也没有被 经过严格测试,但它绝对适用于您的特定用例。还, 这不一定是您希望在生产环境中运行该应用程序的方式。你 必须创建某种应用程序工厂来完成它。再一次,我高度 建议查看 flask 的内部结构,让它做你想做的事。你 可能还想看看 Flask 提供的基于类的 View 或蓝图。 他们能够做一些类似于你在这里的事情。授予,使用 它们非常不同,我不知道设置实例属性 可以使用 Vanilla 蓝图。同样,您可以随时扩展 :-)

关于python - Flask 可以提供 CherryPy 风格的路由吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11991212/

相关文章:

python - Cherrypy:多处理

CherryPy HTTPError 自定义响应处理(*NOT* HTML)

python - Keras 在预测时加载神经网络的权重/错误

python - 按当前时间查询(postgres、psycopg2、python)

python - SqlAlchemy delete() 函数不起作用

python - 棉花糖模式加载只返回值

python - 在 cherrypy 中成功快速启动后启动后台进程

python - PyAutoGUIlocateOnScreen 方法中 minSearchTime 参数的目标是什么?

python - 无法使用 subprocess.call 执行 "sudo su - postgres"

python - Numpy - 矩阵乘法返回 ndarray,而不是总和