首页  >  文章  >  后端开发  >  设计纯Python Web框架

设计纯Python Web框架

DDD
DDD原创
2024-09-19 06:21:33641浏览

Web 开发是最流行的编程用例之一。 Python 是世界上最流行的编程语言之一。那么为什么我们不能用 Python 构建 Web 应用程序呢?

制作 UI 应该很简单,但即使您的团队中有出色的工程师,学习新语言和工具的开销也是一个巨大的障碍。通常,制作 UI 可能比实际工作更困难!

总长DR

在底层,Reflex 应用程序编译为 React 前端应用程序和 FastAPI 后端应用程序。仅 UI 被编译为 Javascript;所有应用程序逻辑和状态管理都保留在Python中并在服务器上运行。 Reflex 使用 WebSockets 将事件从前端发送到后端,并将状态更新从后端发送到前端。

现有的Python解决方案

已经有几种用 Python 构建应用程序的方法,但没有一个能满足我们的需求。

一方面,像 Django 和 Flask 这样的框架非常适合构建生产级 Web 应用程序。但它们只处理后端 - 你仍然需要使用 JavaScript 和前端框架,以及编写大量样板代码来连接前端和后端。

另一方面,像 Dash 和 Streamlit 这样的纯 Python 库非常适合小型项目,但它们仅限于特定的用例,并且不具备构建完整 Web 应用程序的功能和性能。随着您的应用程序功能和复杂性的增长,您可能会发现自己达到了框架的极限,此时您要么必须限制您的想法以适应框架,要么废弃您的项目并使用“真正的 Web 框架”重建它。

我们希望通过创建一个易于上手且直观的框架来弥合这一差距,同时保持灵活和强大的功能以支持任何应用程序。

反射的目标

  • 纯Python:使用一种语言完成所有事情。
  • 易于上手:无需 Web 开发经验即可轻松构建您的想法。
  • 完全灵活性:Web 应用程序应与传统 Web 框架的可定制性和性能相匹配。
  • 包含电池:处理从前端到后端再到部署的全栈。

现在让我们深入了解我们如何构建 Reflex 来实现这些目标。

反射架构

全栈网络应用程序由前端和后端组成。前端是用户界面,充当在用户浏览器上运行的网页。后端处理逻辑和状态管理(例如数据库和 API),并在服务器上运行。

在传统的 Web 开发中,这些通常是两个独立的应用程序,并且通常是用不同的框架或语言编写的。例如,您可以将 Flask 后端与 React 前端结合起来。使用这种方法,您必须维护两个单独的应用程序,并最终编写大量样板代码来连接前端和后端。

我们希望通过在单个代码库中定义前端和后端,同时使用 Python 来完成所有操作,从而简化 Reflex 中的此过程。开发人员只需担心应用程序的逻辑,而不用担心低级实现细节。

Designing a Pure Python Web Framework

前端

我们希望 Reflex 应用程序对于最终用户来说看起来和感觉就像传统的 Web 应用程序,同时仍然易于开发人员构建和维护。为此,我们建立在成熟且流行的网络技术之上。

当您反射运行您的应用程序时,Reflex 会将前端编译为单页 Next.js 应用程序,并将其提供给您可以在浏览器中访问的端口(默认为 3000)。

前端的工作是反映应用程序的状态,并在用户与 UI 交互时将事件发送到后端。前端没有运行任何实际逻辑。

成分

反射前端是使用可以组合在一起创建复杂 UI 的组件构建的。我们不使用混合 HTML 和 Python 的模板语言,而是使用 Python 函数来定义 UI。

在底层,组件编译为 React 组件。

我们的许多核心组件都基于流行的 React 组件库 Radix。我们还有许多其他用于绘图、数据表等的组件。

我们选择React是因为它是一个拥有庞大生态系统的流行库。我们的目标不是重新创建 Web 生态系统,而是让 Python 开发人员可以使用它。

如果我们没有他们需要的组件,这也允许我们的用户携带他们自己的组件。用户可以封装自己的React组件,然后发布给其他人使用。随着时间的推移,我们将构建我们的第三方组件生态系统,以便用户可以轻松找到和使用其他人构建的组件。

造型

我们希望确保 Reflex 应用程序开箱即用时看起来不错,同时仍然让开发人员完全控制其应用程序的外观。

我们有一个核心主题系统,可让您在整个应用程序中设置高级样式选项,例如深色模式和强调色,以赋予其统一的外观和感觉。

除此之外,还可以使用 CSS 的全部功能来设计 Reflex 组件的样式。我们利用 Emotion 库来允许“CSS-in-Python”样式,因此您可以将任何 CSS prop 作为关键字参数传递给组件。这包括通过传递值列表来响应的 props。

后端

在 Reflex 中,只有前端编译为 Javascript 并在用户的浏览器上运行,而所有状态和逻辑都保留在 Python 中并在服务器上运行。当您反射运行时,我们启动一个 FastAPI 服务器(默认在端口 8000),前端通过 websocket 连接到该服务器。

所有状态和逻辑都在 State 类中定义。

状态由 vars事件处理程序组成。

变量是应用程序中可能随时间变化的任何值。它们被定义为 State 类上的类属性,并且可以是任何可以序列化为 JSON 的 Python 类型。

事件处理程序是 State 类中的方法,当用户与 UI 交互时调用。它们是我们在 Reflex 中修改变量的唯一方法,并且可以调用它们来响应用户操作,例如单击按钮或在文本框中键入。

由于事件处理程序在后端运行,因此您可以在其中使用任何 Python 库。

Designing a Pure Python Web Framework

事件处理

通常在编写 Web 应用程序时,您必须编写大量样板代码来连接前端和后端。使用 Reflex,您不必担心这一点 - 我们为您处理前端和后端之间的通信。开发人员只需编写事件处理程序逻辑,当变量更新时,UI 就会自动更新。

事件触发器

用户可以通过多种方式与 UI 交互,例如单击按钮、在文本框中键入或将鼠标悬停在元素上。在 Reflex 中,我们将这些称为事件触发器

事件队列

在前端,我们维护所有待处理事件的事件队列。一个事件由三个主要数据组成:

  • 客户端令牌:每个客户端(浏览器选项卡)都有一个唯一的令牌来识别它。这让后端知道要更新哪个状态。
  • 事件处理程序:在状态上运行的事件处理程序。
  • 参数:传递给事件处理程序的参数。

当事件被触发时,它会被添加到队列中。
我们有一个处理标志来确保一次只处理一个事件。这确保了状态始终一致,并且两个事件处理程序同时修改状态时不存在任何竞争条件。但也有例外,例如后台事件,它允许您在后台运行事件而不阻塞 UI。

事件准备好处理后,就会通过 WebSocket 连接发送到后端。

状态经理

收到事件后,就会在后端进行处理。

Reflex 使用 状态管理器 来维护客户端令牌与其状态之间的映射。默认情况下,状态管理器只是内存中的字典,但可以扩展以使用数据库或缓存。在生产中,我们使用 Redis 作为状态管理器。

事件处理

一旦我们获得了用户的状态,下一步就是使用参数运行事件处理程序。

状态更新

每次事件处理程序返回(或产生)时,我们都会将状态保存在状态管理器中,并将状态更新发送到前端以更新 UI。

为了在状态增长时保持性能,Reflex 在内部跟踪在事件处理程序期间更新的变量(脏变量)。
当事件处理程序完成处理后,我们找到所有脏变量并创建一个状态更新以发送到前端。

我们将新状态存储在状态管理器中,然后将状态更新发送到前端。
然后前端更新 UI 以反映新状态。

结论

我希望这可以很好地概述 Reflex 的底层工作原理。我们将发布更多帖子来分享我们如何通过状态分片和编译器优化等功能使 Reflex 具有可扩展性和高性能。

以上是设计纯Python Web框架的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn