WxPython跨平台开发框架之主从表展示和录入的界面处理--产品报价单和明细记录的处理
我们在前面随笔《Vue3+ElementPlus的BS端主从表的快速开发》了解了Vue3+ElementPlus的BS端主从表的实现,了解了大概的设计和界面设计方式,我们现在切换一下,看看如何结合FastAPI+WxPython实现主从表界面的展示和编辑处理的。
FastAPI的后端采用控制器基类继承方式提供标准化接口,SqlALchemy提供的数据ORM管理,相关代码通过代码生成工具快速生成,包括后端的API接口定义类,SqlALchemy模型类、DTO对象类,以及前端的界面生成等工作。本篇随笔主要介绍WxPython跨平台开发框架之主从表展示和录入的界面处理--产品报价单和明细记录的处理。
1、FastAPI实现主从表数据接口和SqlAlchemy的数据处理
WxPython跨平台开发框架全部采用Python语言进行开发,包括后端的内容,采用 基于SqlAlchemy+Pydantic+FastApi 的后端框架,FastAPI启动后,进入Swagger页面如下所示,列出每个业务表的相关接口。

以上就是常规化的接口,包括单个获取、ID存在、条件查询、分页查询、数量查询、增加、删除、更新等标准化接口,这些基础类接口一般封装在API的控制器基类中。
该后端接口采用统一的接口协议,标准协议如下所示。
{
"success": false,
"result": T ,
"targetUrl": "string",
"UnAuthorizedRequest": false,
"errorInfo": {
"code": 0,
"message": "string",
"details": "string"
}
}
常规化的接口是结合泛型的方式,这样定义可以很好的抽象不同的业务类接口到基类控制器中,如下是FastApi 后端的基类控制器定义。

有了上面基类定义好的常规化接口,子类只需要继承基类控制器即可获得强大的功能接口了。
一般API控制器的子类,只需要继承基类就可以了,额外增加的接口按常规化的设计函数即可,可以参考基类的做法来写各种(GET、PUT、DELETE、POST)的处理函数。

我们来看看对于产品报价单和明细记录的处理,这两个代表不同的业务表,我们可以分开管理,通过约束他们的记录关系实现主从表弹性化的管理。
如对于主表,我们在基类接口外定义多两个函数,主要就是删除主表的时候,同时移除明细记录的关联操作。
from fastapi import APIRouter, Depends, HTTPException, Query, Request, Path, Body ..................
# 创建路由,用于处理自定义接口
router = APIRouter() @router.get(
"byorderno/{orderno}",
response_model=AjaxResponse[QuotationDto | None],
summary="根据报价单编号获取对象信息",
dependencies=[DependsJwtAuth],
)
async def find_by_orderno(
orderno: Annotated[str | None, Path(description="订单编号")],
request: Request,
db: AsyncSession = Depends(get_db),
):
# ip = await get_request_ip(request)
item = await quotation_crud.get_by_column(db, "handno", orderno)
item = QuotationDto.model_validate(item) if item else None
return AjaxResponse(item) @router.delete(
"quotation-related/{id}",
response_model=AjaxResponse[bool | None],
summary="删除报价单及明细信息",
dependencies=[DependsJwtAuth],
)
async def delete_quotation_related(
id: Annotated[str | None, Path(description="报价单ID")],
request: Request,
db: AsyncSession = Depends(get_db),
):
# ip = await get_request_ip(request)
#获取记录信息
item = await quotation_crud.get(db, id)
if not item:
return AjaxResponse(False) # 删除相关的明细记录
res = await quotationdetail_crud.delete_by_column(db, "orderno", item.handno)
if res:
# 再删除报价单
await quotation_crud.delete_byid(db, id)
return AjaxResponse(res) # 使用基类控制器,可以继承常规CRUD的接口,并自动生成路由,依赖注入,数据库连接等功能 ——构建方式2
controller = BaseController[Quotation, str, QuotationPageDto, QuotationDto](
quotation_crud,
pagedto_class=QuotationPageDto,
dto_class=QuotationDto,
router=router,
)
controller.init_router() # 初始化常规CRUD等接口的路由
而报价单明细业务控制器,主要需要根据报价单号(订单号)获取明细的接口
from fastapi import APIRouter, Depends, HTTPException, Query, Request, Path, Body from typing import Type, TypeVar, Generic, List, Dict, Any, Optional, Annotated
from datetime import datetime
from sqlalchemy.ext.asyncio import AsyncSession from schemas.base import AjaxResponse, ErrorInfo, ListResult, PagedResult
from api.base_controller import BaseController
from db.session_async import get_db
from common.jwt import DependsJwtAuth from models.quotationdetail import QuotationDetail
from schemas.quotationdetail import QuotationDetailDto, QuotationDetailPageDto
from crud.quotationdetail import quotationdetail as quotationdetail_crud
from crud.operationlog import operationlog as operationlog_crud
from utils.request_parse import get_request_ip # 创建路由,用于处理自定义接口
router = APIRouter() @router.get(
"/by-orderno",
response_model=AjaxResponse[List[QuotationDetailDto] | None],
summary="根据订单编号获取记录",
dependencies=[DependsJwtAuth],
)
async def get_by_orderno(
orderno: Annotated[str | None, Query(description="订单编号")],
request: Request,
db: AsyncSession = Depends(get_db),
):
# ip = await get_request_ip(request)
items = await quotationdetail_crud.get_by_orderno(db, orderno)
# print(len(items))
items = [QuotationDetailDto.model_validate(item) for item in items]
return AjaxResponse(items) @router.delete(
"/by-orderno/{orderno}",
response_model=AjaxResponse[bool | None],
summary="根据订单编号删除所有明细记录",
dependencies=[DependsJwtAuth],
)
async def delete_by_orderno(
orderno: Annotated[str | None, Path(description="订单编号")],
request: Request,
db: AsyncSession = Depends(get_db),
):
res = await quotationdetail_crud.delete_by_attributes(db, QuotationDetail.orderno == orderno)
return AjaxResponse(res) # 使用基类控制器,可以继承常规CRUD的接口,并自动生成路由,依赖注入,数据库连接等功能
controller = BaseController[QuotationDetail, str, QuotationDetailPageDto, QuotationDetailDto](
quotationdetail_crud,
pagedto_class=QuotationDetailPageDto,
dto_class=QuotationDetailDto,
router=router,
)
controller.init_router() # 初始化常规CRUD等接口的路由
由于基类控制器接口的标准化,我们根据框架后端的接口进行前端API调用类的封装处理,从而实现业务基类调用接口的统一封装,简化代码。这样增删改查等处理的接口都可以抽象到BaseApi里面了。
如对于权限模块,我们涉及到的用户管理、机构管理、角色管理、菜单管理、功能管理、操作日志、登录日志等业务类,那么这些类继承BaseApi,就会具有相关的接口了,如下所示继承关系。

2、基于SqlAlchemy实现的业务模型
FastAPI负责提供数据的API接口,底层的数据处理,通过SqlAlchemy + MongoDB 实现多种数据库的数据管理,如对于MySQL、Postgresql、SQLite、Oracle、MongoDB等进行接入和数据交换处理。
对于常规的业务表,我们采用SqlAlchemy实现数据库的ORM管理的,SqlAlchemy也是Python领域中非常强大的ORM管理模块之一, 它让你用 Python 对象来操作数据库,而不是手写 SQL 语句。
一般我们先定义好模型的基类,提供简单的封装

然后在业务类里面继承它即可

报价单的明细表也是类似的

这些模型类和对应接口的DTO类只需要在代码生成工具中进行一键生成就可以了,不用编写。
在代码生成工具 Database2Sharp 打开数据库列表后,右键菜单可以选择生成对应的Python+FastApi后端项目,如下界面所示。

选中相关的表后,一键可以生成各层的类文件,其中包括最为繁琐的Model映射类信息。如下是生成的相关类的界面效果。

2、WxPthon实现基于Python桌面端主从表的数据处理
我们知道,一般对于单表来说,业务和界面会相对比较简单,如下面的界面效果,在Windows下客户信息的列表管理和数据编辑界面如下所示。

而对于主从表,一般除了主业务表外,会关联一个到多个的明细表,对于报价单来说,就只有一个明细表,如下所示是具体的界面列表展示。

对于列表的主从表关联关系,没有太多好说的,就是增加了一个明细表的处理展示
对于主从表编辑界面来说,就需要复杂处理一些,在表格需要直接编辑录入并保存明细的操作处理,如下是主从表的编辑界面的实现效果。

其主要就是在第一次创建的时候,对表格数据类进行设置

表格的数据直接录入,一般不是仅仅的通过文本框的录入,一般录入有选择表的记录,下拉类表、复选框、图像、数值、颜色等等特殊的录入的。
如自定义数据列表选择界面,我通过定义一个产品的数据列表展示供选择,单击产品编码处,弹出一个选择框进行选择。

为了实现对表格数据单元格的单击监控,我们绑定了对应的事件。
AsyncBind(wx.grid.EVT_GRID_CELL_LEFT_CLICK, self.on_cell_left_click, self.sub_grid)
然后对事件进行实现即可。

下拉列表则是通过绑定固定列表,或者字典类型的方式实现字典下拉列表选择

初始化字典列表很容易,如下代码所示。

其他案例可以参考测试效果,支持多种数据输入处理,测试界面效果如下所示。

以上就是对于WxPython应用,结合前后端的处理,实现了主从表展示和录入的界面处理--产品报价单和明细记录的处理。
WxPython跨平台开发框架之主从表展示和录入的界面处理--产品报价单和明细记录的处理的更多相关文章
- DevExpress主从表 按组分页一组不足一页为一页--以此记录
本文的主要是说明Dev的报表的主从表,主从表的每一组显示在一页,当一组超出一页,第二页只显示第一组的. 一.每上报表设置图 简单设计图如上 二.后台代码 报表页代码 public partial cl ...
- 在GridControl表格控件中实现多层级主从表数据的展示
在一些应用场景中,我们需要实现多层级的数据表格显示,如常规的二级主从表数据展示,甚至也有多个层级展示的需求,那么我们如何通过DevExpress的GridControl控表格件实现这种业务需求呢?本篇 ...
- RDIFramework.NET V3.3 WinForm版新增订单管理主从表事例
功能描述 无论什么系统,除了常规的单表处理外,主从表的应用都是非常普遍的,RDIFramework.NET V3.3 WinForm版本中新增了一个主从表的事例供大家参考.主从表的界面设计大同小异,主 ...
- Winform开发框架之单据窗体生成(主从表,流水单号)
源码地址:https://github.com/GarsonZhang/GZFramework.ShareDemo 前言 1.在开始本节前请先重置代码为 chapter-03-start 懒人地址:h ...
- 代码生成工具Database2Sharp中增加视图的代码生成以及主从表界面生成功能
在代码生成工具的各种功能规划中,我们一向以客户的需求作为驱动,因此也会根据需要增加一些特殊的功能或者处理.在实际的开发中,虽然我们一般以具体的表进行具体业务开发,但是有些客户提出有时候视图开发也是很常 ...
- ASPxGridView中如何对主从表绑定数据
注:在从表的aspxgridview中的(OnDataBinding()事件中绑定数据)-----代码如下 //绑定属性值表protected void grid2_sonTable_DataBind ...
- Winform界面中主从表编辑界面的快速处理
在Winform开发中,我们往往除了常规的单表信息录入外,有时候设计到多个主从表的数据显示.编辑等界面,单表的信息一般就是控件和对象实体一一对应,然后调用API保存即可,主从表就需要另外特殊处理,本随 ...
- DWZ主从表界面唯一性验证(后台验证)(三)
之前的博客介绍了前台自写js来验证主动表的唯一性,除了前台的验证,我也学习了后台的一些判断. 再次介绍一下背景需求: 利用DWZ的主从表结构批量添加课程信息,在提交表单后,触发Action事件 1.是 ...
- 如何: 在 VS中的设计时刻主从表绑定控件到数据库
这个示例展示了如何在 Visual Studio 2005 的设计时刻,把一个 data-aware 控件 (XtraGrid.XtraPivotGrid.XtraVerticalGrid 等) 绑定 ...
- EF里单个实体的增查改删以及主从表关联数据的各种增删 改查
本文目录 EF对单个实体的增查改删 增加单个实体 查询单个实体 修改单个实体 删除单个实体 EF里主从表关联数据的各种增删改查 增加(增加从表数据.增加主从表数据) 查询(根据主表找从表数据.根据从表 ...
随机推荐
- SciTech-EECS-Circuits-电路稳定性: 温度补偿 的几种方式对比: 响应时问、精度、动态范围、线性度、稳定度
电路稳定性: 温度稳定性 测试的几种方式: 电吹风加热 冰箱(-5度) + 烤箱(50度/70度) 改进 "文氏电桥振荡" 电路 的"热稳定性温度补偿" 网上找 ...
- OpenList基本使用流程
1. 完成项目拉取后要做的操作 1.1 启动与登录 启动方式:在 .exe 文件的存放位置输入cmd打开命令行 在命令行中输入: openlist.exe server 初次打开时会给出初始密码,将初 ...
- mybatis-Plus 实践篇之逆向工程 --九五小庞
目录 概念 特性: 新建Spring项目,引入依赖 yaml配置 配置代码生成器 运行验证 验证swagger 初次听说mybatis-plus感觉这东西取名字都很有意思,像极了现在的iPhone 到 ...
- Unity框架 EcsRx
文档:https://ecsrx.gitbook.io/project/ github: https://github.com/EcsRx/ecsrx.unity
- Origin图表技巧之绘制带辅助面的3D折线图
折线图是科研中经常用到的图表之一,它通过线的升降变化显示数据的变化趋势,今天给大家分享绘制三维折线图的操作方法: 操作步骤: 1.先打开Origin2024软件,然后在Book1中输入如下示例数据: ...
- 2024巴黎奥运会VIS视觉设计分享学习
2024年巴黎奥运会的视觉识别系统(VIS)以其独特的设计和创意,展现了法国的优雅与活力.该设计融合了现代感与传统元素,以巴黎标志性的建筑和文化为灵感,创造出一系列令人印象深刻的视觉符号. 色彩上,采 ...
- 十年大厂员工终明白:MySQL性能优化的尽头,是对B+树的极致理解
存储引擎 存储引擎是数据库管理系统(DBMS)或键值存储系统的核心组件,它定义了数据在持久化存储介质上如何组织.存储.检索和管理.不同的存储引擎针对特定负载(如读密集型.写密集型.混合型)和数据模型( ...
- [题解]AtCoder Beginner Contest 394(ABC394) A~G
A - 22222 遍历字符串\(s\),按题意输出所有2即可. 点击查看代码 #include<bits/stdc++.h> #define int long long using na ...
- mac外接键盘HOME、END键问题
mac老用户应该都知道,MAC自带的键盘的 cmd+左/右箭头 快捷键实际上就对应的是 HOME 和 END: 但是如果外接了自带 HOME 和 END 键的键盘,就会发生尴尬的事情,你会发现HOME ...
- LiveNVR安防Onvif_RTSP流媒体服务-服务器配置及带宽消耗计算参考
LiveNVR Onvif/RTSP流媒体服务,支持RTSP稳定拉流接入,支持Onvif协议接入,支持RTMP/HLS/HTTP-FLV分发,将传统安防监控设备互联化,无插件直播等. 理论1Mbps存 ...