"如何为类添加flask的REST行为?使用蓝图吗?"

2024-04-19 04:52:09 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在处理一个python应用程序,它由多个分布式轻量级组件组成,这些组件使用RabbitMQ&;Kombu进行通信。

一个组件监听两个队列,并且可以在每个队列上接收多个消息类型。子类可以通过注册自定义处理程序重写如何处理每个消息类型。 这一切都很好。

我现在有一个附加的要求,即每个组件必须有一个基本的REST/HTML接口。您可以将浏览器指向正在运行的组件,并获取其当前正在执行的操作的实时信息(正在处理的消息、cpu使用率、状态信息、日志等)

它需要很轻,所以经过一些研究,我决定烧瓶(但我对建议持开放态度)。在伪代码中,这意味着:

class Component:
   Queue A
   Queue B
   ...
   def setup(..):
     # connect to the broker & other initialization

   def start(..):
     # start the event loop and wait for work  

   def handle_msg_on_A(self,msg):
     # dispatch a msg to a handler depending on the msg type

   def handle_msg_on_B(self,msg):
     ...

   ...

以及添加许多视图方法:

   @app.route('/')
   def web_ui(self):
      # render to a template

   @app.route('/state')
   def get_state(self):
      # REST method to return some internal state info as JSON

   ...

然而,将web UI固定到这样的类上会破坏SOLID原则并带来继承问题(子类可能希望显示更多/更少的信息)。装饰器不是继承的,因此每个视图方法都需要显式重写和重新装饰。也许使用mixin+反射可以起到某种作用,但感觉有点老套。

相反,使用组合可以工作:将web内容放在一个单独的类中,该类将url路由委托给嵌套组件上一组固定的、预定义的多态方法。 这样,组件就不知道烧瓶的存在,代价是灵活性的损失(可用的方法是固定的)。

我现在发现了Flask blueprintsApplication Dispatching,看起来它们可以带来更好、更可扩展的解决方案。然而,我还没有把我的头裹在他们身上。

我觉得我错过了一个设计模式,希望有人与更多瓶福或经验与这类问题可以评论。


Tags: theto方法selfweb信息消息类型
1条回答
网友
1楼 · 发布于 2024-04-19 04:52:09

烧瓶0.7中悄悄地引入了一些您可能感兴趣的内容-Pluggable Views。这些是基于类的端点,而不是基于函数的端点,因此可以使用^{}方法来管理状态转换(仅在需要时重写它)。

与使用应用程序分派不同,这样做的好处是,您可以在整个应用程序中获得url_for支持(而不必在跨应用程序边界的url中硬编码)。您必须确定这是否是应用程序可能遇到的问题。

在伪代码中:

# File: Components.py
from flask.views import View

class Component(View):
    # Define your Component-specific application logic here

    dispatch_request(self, *url_args, **url_kwargs):
        # Define route-specific logic that all Components should have here.
        # Call Component-specific methods as necessary

class Tool_1(Component):
    pass

class Tool_2(Component):
    # Override methods here

# File: app.py
from flask import Flask
from yourapplication import Tool_1, Tool_2

app = Flask()

# Assuming you want to pass all additional parameters as one argument
app.add_url_rule("/tool_1/<path:options>", "tool1", view_func=Tool_1.as_view())

# Assuming you want to pass additional parameters separately
tool_2_view = Tool_2.as_view()
app.add_url_rule("/tool_2/", "tool2", view_func=tool_2_view )
app.add_url_rule("/tool_2/<option>", "tool2", view_func=tool_2_view)
app.add_url_rule("/tool_2/<option>/<filter>", "tool2", view_func=tool_2_view)

如果您有一系列逻辑连接在一起的组件,并且您不想记住将/prefix放在每个组件的add_url_rule调用前面,则可以将蓝图添加到组合中。但是如果你有一系列的组件,它们彼此独立,这就是我要使用的模式。

*。另一方面,如果它们需要相互隔离,我将使用文档中推荐的应用程序分派模式。

相关问题 更多 >