实践reflex:项目架构解析

embedded/2024/9/20 1:27:20/ 标签: linux, 运维, 服务器

 reflex 是一个使用纯Python构建全栈web应用的库,但是需要使用node,所以你懂的。

reflex安装:实践reflex:一个使用纯Python构建全栈web应用的库-CSDN博客

创建hello项目

(base) sky@ub:~$ mkdir hello
(base) sky@ub:~$ cd hello/
(base) sky@ub:~/hello$ reflex init
─────────────────────── Initializing hello ────────────────────────
[06:42:32] Initializing the web directory.           console.py:104
Warning: Failed to fetch templates. Falling back to default 
template.
[06:42:50] Initializing the app directory.           console.py:104
Success: Initialized hello

项目路径结构:

hello
├── .web
├── assets
├── hello
│   ├── __init__.py
│   └── hello.py
└── rxconfig.py

 其中.web是隐藏目录,需要ls -la 才能看到。

.web 

这是编译的Javascript文件的存储位置。您永远不需要触摸此目录,但它对调试很有用。

每个Reflex页面都将编译为.web/pages目录中相应的.js文件。

assets资产

目录是您可以存储任何您想要公开可用的静态资产的地方。这包括图像、字体和其他文件。

例如,如果您将图像保存到assets/image.png,您可以从应用程序中显示它,如下所示:

rx.image(src="image.png")

主目录hello

每个项目的主目录,都跟项目名字一样。

初始化您的项目会创建一个与应用程序同名的目录。您将在这里编写应用程序的逻辑。

Reflex在hello/hello.py文件中生成一个默认应用程序。您可以修改此文件来自定义您的应用程序。

配置

rxconfig.py文件

应用程序模块

Reflex根据config中的app_name导入主应用程序模块,该模块必须将模块级全局命名app定义为rx.App的实例

主应用程序模块负责导入构成应用程序的所有其他模块,并定义app = rx.App()

包含页面、状态和模型的所有其他模块必须由主应用程序模块或软件包导入,以便Reflex将它们包含在编译的输出中。

更详细的说明

页面包:example_big_app/pages

所有复杂的应用程序都将有多个页面,因此建议创建example_big_app/pages作为软件包。

  1. 此软件包应在应用程序中每页包含一个模块。
  2. 如果特定页面取决于状态,则该子状态应在与页面相同的模块中定义。
  3. 返回页面的函数应该用rx.page()进行装饰,以便将其作为路由添加到应用程序中。
import reflex as rxfrom ..state import AuthStateclass LoginState(AuthState):def handle_submit(self, form_data):self.logged_in = authenticate(form_data["username"], form_data["password"])def login_field(name: str, **input_props):return rx.hstack(rx.text(name.capitalize()),rx.input(name=name, **input_props),width="100%",justify="between",)@rx.page(route="/login")
def login():return rx.card(rx.form(rx.vstack(login_field("username"),login_field("password", type="password"),rx.button("Login"),width="100%",justify="center",),on_submit=LoginState.handle_submit,),)

模板:example_big_app/template.py

大多数应用程序在页面之间保持一致的布局和结构。在单独的模块中定义此通用结构有助于在构建单个页面时轻松共享和重复使用。

最佳实践

  1. 将常见的前端用户界面元素分解为返回组件的函数。
  2. 如果一个函数接受返回组件的函数,它可以用作装饰器,如下所示。
    from typing import Callableimport reflex as rxfrom .components.menu import menu
    from .components.navbar import navbardef template(page: Callable[[], rx.Component]
    ) -> rx.Component:return rx.vstack(navbar(),rx.hstack(menu(),rx.container(page()),),width="100%",)
    

状态管理

进入其它状态

在以前的版本中,如果应用程序想要将设置与用于修改的页面或组件一起存储在SettingsState中,则需要访问这些设置的任何其他具有事件处理程序的状态必须从SettingsState继承,即使其他状态大多是正交的。另一种状态现在也必须始终加载设置,即使对于不需要访问它们的事件处理程序也是如此。

更好的策略是仅从需要访问子状态的事件处理程序中按需加载所需状态。

设置组件

example_big_app/components/settings.py
import reflex as rxclass SettingsState(rx.State):refresh_interval: int = 15auto_update: bool = Trueprefer_plain_text: bool = Trueposts_per_page: int = 20def settings_dialog():return rx.dialog(...)

帖子页面:example_big_app/pages/posts.py

此页面加载SettingsState,以确定每页显示多少个帖子以及刷新频率。

import reflex as rxfrom ..models import Post
from ..template import template
from ..components.settings import SettingsStateclass PostsState(rx.State):refresh_tick: intpage: intposts: list[Post]async def on_load(self):settings = await self.get_state(SettingsState)if settings.auto_update:self.refresh_tick = (settings.refresh_interval * 1000)else:self.refresh_tick = 0async def tick(self, _):settings = await self.get_state(SettingsState)with rx.session() as session:q = (Post.select().offset(self.page * settings.posts_per_page).limit(settings.posts_per_page))self.posts = q.all()def go_to_previous(self):if self.page > 0:self.page = self.page - 1def go_to_next(self):if self.posts:self.page = self.page + 1@rx.page(route="/posts", on_load=PostsState.on_load)
@template
def posts():return rx.vstack(rx.foreach(PostsState.posts, post_view),rx.hstack(rx.button("< Prev", on_click=PostsState.go_to_previous),rx.button("Next >", on_click=PostsState.go_to_next),justify="between",),rx.moment(interval=PostsState.refresh_tick,on_change=PostsState.tick,display="none",),width="100%",)

共同状态:example_big_app/state.py

由多个页面或组件共享的通用状态和子状态应在单独的模块中实现,以避免循环导入。此模块不应在应用程序中导入其他模块。

组件的可重复使用性

在Reflex中重复使用组件的主要机制是定义一个返回组件的函数,然后在需要该功能的地方简单地调用它。

组件函数通常不应将任何状态类作为参数,而是倾向于导入所需的状态并直接访问类上的变量。

记忆功能以提高性能

在大型应用程序中,如果一个组件有许多子组件或在大量位置使用,它可以提高编译和运行时性能,使用@lru_cache装饰器对函数进行内啮。

要回忆foo组件以避免多次重新创建,只需将@lru_cache添加到函数定义中,该组件将仅每组唯一参数创建一次。

from functools import lru_cacheimport reflex as rxclass State(rx.State):v: str = "foo"@lru_cache
def foo():return rx.text(State.v)def index():return rx.flex(rx.button("Change",on_click=State.set_v(rx.cond(State.v != "bar", "bar", "foo")),),*[foo() for _ in range(100)],direction="row",wrap="wrap",)

示例_大_应用程序/组件

此软件包包含应用程序的可重复使用部分,例如页眉、页脚和菜单。如果特定组件需要状态,则子状态可以在同一区域模块中定义。组件模块中定义的任何子状态应仅包含与该单个组件相关的字段和事件处理程序。

外部组件

Reflex 0.4.3引入了对reflex componentCLI命令的支持,这使得它可以轻松捆绑通用功能,作为独立的Python软件包在PyPI上发布,可以在任何Reflex应用程序中安装和使用。

在包装npm组件或其他自包含的功能片段时,将此复杂性移出应用程序本身可能会有所帮助,以便于在其他应用程序中更易于维护和重复使用。

数据库模型:example_big_app/models.py

建议在单个文件中实现所有数据库模型,以便更容易定义关系和理解整个模式。

然而,如果模式非常大,则有一个models包,在自己的模块中定义了单个模型,这可能是有意义的。

无论如何,单独定义模型允许任何页面或组件导入和使用它们,而无需循环导入。

顶级套餐:example_big_app/__init__.py

这是一个导入所有状态、模型和页面的好地方,这些状态、模型和页面应该是应用程序的一部分。通常,组件和助手不需要导入,因为它们将由使用它们的页面导入(或者它们将未使用)。

from . import state, models
from .pages import (index,login,post,product,profile,schedule,
)__all__ = ["state","models","index","login","post","product","profile","schedule",
]


http://www.ppmy.cn/embedded/108343.html

相关文章

【Azure Redis】Redis-CLI连接Redis 6380端口始终遇见 I/O Error

问题描述 使用Redis-cli连接Redis服务&#xff0c;因为工具无法直接支持TLS 6380端口连接&#xff0c;所以需要使用 stunnel 配置TLS/SSL服务。根据文章(Linux VM使用6380端口(SSL方式)连接Azure Redis (redis-cli & stunnel) &#xff1a; https://www.cnblogs.com/luligh…

模型训练套路(二)

接模型训练套路&#xff08;一&#xff09;http://t.csdnimg.cn/gZ4Fm 得到预测的值&#xff1a;preds[1][1]&#xff0c; 输出目标&#xff1a;inputs target [0][1]&#xff1b; 查看两者的正确率&#xff0c;就看&#xff1a;predsinputs target 输出的结果&#xff1a…

前端WebSocket客户端实现

// 创建WebSocket连接 var socket new WebSocket(ws://your-spring-boot-server-url/websocket-endpoint);// 连接打开时触发 socket.addEventListener(open, function (event) {socket.send(JSON.stringify({type: JOIN, room: general})); });// 监听从服务器来的消息 socke…

K8S日志收集

本章主要讲解在 Kubernetes 集群中如何通过不同的技术栈收集容器的日志&#xff0c;包括程序直接输出到控制台日志、自定义文件日志等。 一、有哪些日志需要收集 为了更加方便的处理异常&#xff0c;日志的收集与分析极为重要&#xff0c;在学习日志收集之前&#xff0c;需要知…

QT基础 QPropertyAnimation简单学习

目录 1.简单介绍 2.使用步骤 3.部分代码示例 4.多项说明 5.信号反馈 6.自定义属性 1. 定义自定义属性 2. 使用 QPropertyAnimation 动画化自定义属性 3. 连接信号和槽 4.注意事项 7.更多高级示例 1.简单介绍 QPropertyAnimation是Qt中的一个类&#xff0c;用于实现属性…

idea安装并使用maven依赖分析插件:Maven Helper

在 IntelliJ IDEA 中安装并使用 Maven Helper 插件可以帮助你更方便地管理 Maven 项目的依赖&#xff0c;比如查看依赖树、排除冲突依赖等。以下是安装和使用 Maven Helper 插件的步骤&#xff1a; 安装 Maven Helper 插件 打开 IntelliJ IDEA 并进入你的项目。 在 IDE 的右下…

百度飞浆OCR半自动标注软件OCRLabel配置【详细

今天帮标注人员写了一份完整的百度飞浆OCR标注软件的安装配置说明书、以供标注人员使用 包括各种环境安装包一起分享出来【conda\python\label项目包、清华源配置文件、pycharm社区版安装包】 提取码&#xff1a;umys 1、解压并安装tools文件下的miniconda,建议安装在D盘下的…

Win32绕过UAC弹窗获取管理员权限

在早些年写一些桌面软件时&#xff0c;需要管理员权限&#xff0c;但是又不想UAC弹窗&#xff0c;所以一般是直接将UAC的级别拉到最低&#xff0c;或者直接禁用UAC的相关功能。 什么是UAC(User Account Control) 用户帐户控制 (UAC) 是一项 Windows 安全功能&#xff0c;旨在保…

Flink SQL 中常见的数据类型

Flink SQL 中常见的数据类型 目标 通过了解Flink SQL 中常见的数据类型,掌握正确编写Flink SQL 语句背景 Apache Flink 支持多种数据类型,这些数据类型被用于 Flink SQL 表达式、Table API 以及 DataStream API 中。以下是 Flink SQL 中常见的数据类型: 基本数据类型 Boo…

<Rust>egui学习之部件(十一):如何在窗口中添加单选框radiobutton部件?

前言 本专栏是关于Rust的GUI库egui的部件讲解及应用实例分析&#xff0c;主要讲解egui的源代码、部件属性、如何应用。 环境配置 系统&#xff1a;windows 平台&#xff1a;visual studio code 语言&#xff1a;rust 库&#xff1a;egui、eframe 概述 本文是本专栏的第十一篇…

算法练习题17——leetcode54螺旋矩阵

题目描述 给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素。 代码 import java.util.*;class Solution {public List<Integer> spiralOrder(int[][] matrix) {// 用于存储螺旋顺序遍历的结果List<Integer>…

学习整理使用jquery实现获取相同name被选中的多选框值的方法

学习整理使用jquery实现获取相同name被选中的多选框值的方法 <html><head><meta charset"gbk"><!-- 引入JQuery --><script src"https://www.qipa250.com/jquery/dist/jquery.min.js" type"text/javascript"><…

flutter开发实战-flutter build web微信无法识别二维码及小程序码问题

flutter开发实战-flutter build web微信无法识别二维码及小程序码问题 GitHub Pages是一个直接从GitHub存储库托管的静态站点服务&#xff0c;‌它允许用户通过简单的配置&#xff0c;‌将个人的代码项目转化为一个可以在线访问的网站。‌这里使用flutter build web来构建web发…

现代计算机中数字的表示与浮点数、定点数

现代计算机中数字的表示与浮点数、定点数 导读&#xff1a;浮点数运算是一个非常有技术含量的话题&#xff0c;不太容易掌握。许多程序员都不清楚使用操作符比较float/double类型的话到底出现什么问题。这篇文章讲述了浮点数的来龙去脉&#xff0c;所有的软件开发人员都应该读…

【网络安全】服务基础第二阶段——第三节:Linux系统管理基础----Linux用户与组管理

目录 一、用户与组管理命令 1.1 用户分类与UID范围 1.2 用户管理命令 1.2.1 useradd 1.2.2 groupadd 1.2.3 usermod 1.2.4 userdel 1.3 组管理命令 1.3.1 groupdel 1.3.2 查看密码文件 /etc/shadow 1.3.4 passwd 1.4 Linux密码暴力破解 二、权限管理 2.1 文件与目…

封装触底加载组件

&#xff08;1&#xff09;首先创建一个文件名为&#xff1a;InfiniteScroll.vue <template><div ref"scrollContainer" class"infinite-scroll-container"><slot></slot><div v-if"loading" class"loading-sp…

nginx 新建一个 PC web 站点

注意&#xff1a;进行实例之前必须完成nginx的源码编译。&#xff08;阅读往期文章完成步骤&#xff09; 1.编辑nginx的配置文件&#xff0c;修改内容 [rootlocalhost ~]# vim /usr/local/nginx/conf/nginx.conf 2.创建新目录/usr/local/nginx/conf.d/&#xff0c;编辑新文件…

【激活函数总结】Pytorch中的激活函数详解: ReLU、Leaky ReLU、Sigmoid、Tanh 以及 Softmax

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推荐------》 一、AI应用软件开发实战专栏【链接】 项目名称项目名称1.【人脸识别与管理系统开发…

问:你知道IO和NIO有哪些区别不?

一、先表示一下_ Java IOJava NIO主要特点面向流&#xff08;Stream&#xff09;的I/O操作面向缓冲区&#xff08;Buffer&#xff09;和通道&#xff08;Channel&#xff09;的I/O操作&#xff0c;支持非阻塞I/O和选择器&#xff08;Selector&#xff09;常用方法InputStream、…

el-table 单元格,双击编辑

el-table 单元格&#xff0c;双击编辑 实现效果 代码如下 <template><el-table :data"tableData" style"width: 100%"><el-table-column prop"name" label"姓名" width"180"><template slot-scope&q…