Pydantic与Sqlalchemy数据模型的枚举类型实践

说明:

  • 乍看时以为很容易的东西,摸索实践后才知道窍门
  • 实战中我是用Tinyint / Interger 作为保存 enum对象数值的字段类型, 而不是用数据库中提供的ENUM类型字段,因为有更好的扩展性,性能,节省空间作为使用理由
  • Pydantic Model (PM) 与 Sqlalchemy Model (SM) 的关系是数据模型的外在与内部持久化的两种表现形式, PM负责数据模型的输入输出(规则验证 / 过滤 / 表达转换),SM负责数据模型的具体存储表达

开始时遇到的问题:

  • 因为没有打开use_enum_values = True, 致使保存时总出错: “sqlalchemy.exc.DataError: (asyncmy.errors.DataError) (1366, "Incorrect integer value: 'DeviceType.HOST' for column 'type' at row 1")”
  • 怀疑人生后,用官方的例子用数据库的ENUM类型做保存,成功后觉得不符合要求,弃之
    from sqlalchemy import Enum
    ...
    type = mapped_column(Enum(DeviceType), nullable=False, default=DeviceType.HOST, comment='类型: 1 IOT传感器 Sensor 2 交互设备 Host 3 软件应用 App')

修改好的实例:

有一个设备表,里面有一个type列(Tinyint),用于保存设备类型,结构如下:

(Sqlalchemy Model)

from typing import List, Optionalfrom sqlalchemy import BigInteger, Column, DateTime, ForeignKeyConstraint, Index, DECIMAL, Integer, String, Table, Text, text
from sqlalchemy.dialects.mysql import TINYINT
from sqlalchemy.orm import Mapped, declarative_base, mapped_column, relationship
from sqlalchemy.orm.base import Mappedfrom sqlalchemy.orm import relationship, Mapped, mapped_column
from db.db_base import BaseModel
from .data_types import DeviceTypeclass Device(BaseModel):__tablename__ = 'ia_iot_device'__table_args__ = (Index('Index_1', 'label'),Index('Index_2', 'name'),Index('Index_3', 'code'))id = mapped_column(BigInteger, primary_key=True)type = mapped_column(TINYINT, default=DeviceType.HOST, comment='类型: 1 IOT传感器 Sensor 2 交互设备 Host 3 软件应用 App')code = mapped_column(String(255, 'utf8mb4_general_ci'), comment='编码,唯一')name = mapped_column(String(255, 'utf8mb4_general_ci'), comment='设备名, 如 dev@ip:port')label = mapped_column(String(255, 'utf8mb4_general_ci'), comment='设备标签,客户自定义')product_id = mapped_column(BigInteger, server_default=text("'0'"), comment='产品id')secret = mapped_column(String(255, 'utf8mb4_general_ci'), comment='访问密钥,暂不启用')mac = mapped_column(String(255, 'utf8mb4_general_ci'), comment='物理地址')geo_longitude = mapped_column(String(255, 'utf8mb4_general_ci'), comment='经度')geo_latitude = mapped_column(String(255, 'utf8mb4_general_ci'), comment='纬度')height = mapped_column(DECIMAL(10, 2), server_default=text("'0.00'"), comment='高度')deployment_id = mapped_column(BigInteger, server_default=text("'0'"), comment='部署地方id, 暂没启用')register_ip = mapped_column(String(255, 'utf8mb4_general_ci'), comment='注册IP')env = mapped_column(Text(collation='utf8mb4_general_ci'), comment='环境参数, json格式')memo = mapped_column(Text(collation='utf8mb4_general_ci'), comment='备注')is_bound = mapped_column(TINYINT, server_default=text("'0'"), comment='是否已绑定')state = mapped_column(String(255, 'utf8mb4_general_ci'), comment='实时状态编码')status = mapped_column(TINYINT, server_default=text("'1'"), comment='实体记录状态 1活动 2停用 3伪删除')position = mapped_column(Integer, server_default=text("'0'"), comment='排序优先极, 数字高优先')# created_at = mapped_column(DateTime)# updated_at = mapped_column(DateTime)

data_types.py

import enumclass DeviceType(enum.Enum):'''设备类型'''SENSOR = 1HOST = 2APP = 3

(Pydantic Model) apps\vadmin\iot\schemas\Device.py

要点:告诉Pydantic使用枚举值

class Config:  

        use_enum_values = True

from pydantic import BaseModel, Field, ConfigDict
from core.data_types import DatetimeStr
from apps.vadmin.iot.models.data_types import DeviceTypeclass Device(BaseModel):type: DeviceType | None = Field(None, title="类型: 1 IOT传感器 Sensor 2 交互设备 Host 3 软件应用 App")code: str | None = Field(None, title="编码,唯一")name: str | None = Field(None, title="设备名, 如 dev@ip:port")label: str | None = Field(None, title="设备标签,客户自定义")product_id: int | None = Field(None, title="产品id")secret: str | None = Field(None, title="访问密钥,暂不启用")mac: str | None = Field(None, title="物理地址")geo_longitude: str | None = Field(None, title="经度")geo_latitude: str | None = Field(None, title="纬度")height: float | None = Field(None, title="高度")deployment_id: int | None = Field(None, title="部署地方id, 暂没启用")register_ip: str | None = Field(None, title="注册IP")env: str | None = Field(None, title="环境参数, json格式")memo: str | None = Field(None, title="备注")is_bound: int | None = Field(None, title="是否已绑定")state: str | None = Field(None, title="实时状态编码")status: int | None = Field(None, title="实体记录状态 1活动 2停用 3伪删除")position: int | None = Field(None, title="排序优先极, 数字高优先")class Config:  use_enum_values = True

参考:

- python - Pydantic enum field does not get converted to string - Stack Overflow

- The Type Hierarchy — SQLAlchemy 2.0 Documentation

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/14923.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Git 在Windows上添加文件换行相关设置

Windows使用Git时,如果在提交时希望换行符不变(CRLF换行不转换为LF),core.autocrlf选项可以按照如下设置。 时保留CRLF换行符,检出时转换为LF,core.autocrlf为true: git config --global core.…

pcd点云江湖之处处碰壁:点云文件pcd加载02

江湖好汉,休走,废了半天力气把threejs自带的代码搬迁到自己项目中了,高高兴兴给领导看。领导一句话,顿时无奈:领导曰:点云单色太丑,能不能按照分类展示? 一句话难道英雄好汉&#xf…

#P0564. 数组元素查找升级版

问题描述 给你 n 个数,再给你一个数 k,查找 k 在这 n 个数中第一次出现的位置(从 0 开始计数),不存在输出 No。 输入 多组测试数据,对于每组测试数据: 第一行输入一个整数 n (1 ≤ n ≤ 100…

深入理解Vue 3中的v-if和v-for指令

Vue.js是一款流行的JavaScript框架,其简洁的语法和强大的功能使得前端开发变得更加高效和愉快。在Vue 3中,我们看到了许多新的特性和改进,其中包括了两个最常用的指令之一:v-if和v-for。 1. v-if指令 v-if指令是Vue中最常用的条件…

eclipse配置JDK和Tomcat

eclipse配置JDK jdk配置 配置JDK: 首先,确保JDK已经安装并配置了环境变量。这包括设置JAVA_HOME环境变量,指向JDK的安装目录,以及更新CLASSPATH和PATH环境变量以包含JDK的bin目录。 在Eclipse中,通过Window > Pre…

【Verilog编程题】

20240514 20240515 20240516 题目时序有问题,valid_b在第六位数据的同时拉高,而不是在下一个时钟 20240517 module valid_ready( input clk , input rst_n , input [7:0] data_in , input valid_a , input ready_b , output ready_a , output re…

使用 PyTorch 和 Pandas 进行 Kaggle 房价预测

文章目录 1、环境设置2、数据下载3、数据预处理4、模型构建5、训练和验证6、训练模型并生成预测结果7、完整代码 在本篇博文中,我们将探索如何使用 PyTorch 和 Pandas 库,构建一个用于 Kaggle 房价预测的模型。我们将详细讨论数据加载、预处理、模型构建…

vue注册自定义指令

在 Vue 中,可以通过全局或局部注册自定义指令。下面是一个简单的示例,演示如何在 Vue 中注册一个自定义指令。 首先,我们需要定义一个自定义指令。在 Vue 中,自定义指令可以通过全局或局部注册,并在元素上绑定特定的行…

LaTeX 2022软件安装教程(附软件下载地址)

软件简介: 软件【下载地址】获取方式见文末。注:推荐使用,更贴合此安装方法! LaTeX 2022是基于ΤΕΧ的一种排版系统,特别适用于生成科技和数学文档的高质量打印。它可用于各种文档类型,从简单信函到完整…

Java进阶学习笔记2——static

static: 叫静态,可以修饰成员变量、成员方法。 成员变量按照有无static修饰,分为两种: 类变量:有static修饰,属于类,在计算机中只有一份,会被类的全部对象共享。静态成员变量。 实…

即时通讯ICQ将于2024年6月26日起关闭

即时通讯鼻祖ICQ 将于2024年6月26日起停止服务。 背景 ICQ则是由以色列的Mirabilis公司开发,ICQ发布后不久,腾讯发布了中国版QQ,当时界面和概念上非常类似ICQ,同时期还有微软MSN。 那个时候很多人都认为QQ肯定竞争不过ICQ和MSN&…

慢性乙型肝炎肝脏剪切波弹性成像的深度学习放射学显著改善了肝纤维化的诊断性能 | 文献速递-深度学习结合影像组学

慢性乙型肝炎肝脏剪切波弹性成像的深度学习放射学显著改善了肝纤维化的诊断性能 | 文献速递-深度学习结合影像组学 麦田医学 美好事物中转站 2024-05-21 11:03 Title 题目 Deep learning Radiomics of shear wave elastography significantly improved diagnostic performa…

面试准备-项目【面试准备】

面试准备-项目【面试准备】 面试准备自我介绍:项目介绍: 论坛项目功能总结简介数据库表设计注册功能登录功能显示登录信息功能发布帖子评论私信点赞功能关注功能通知搜索网站数据统计热帖排行缓存 论坛项目技术总结Http的无状态cookie和session的区别为什…

《我的阿勒泰》观后感(二、返璞归真也是一种美)

看了李娟的小说《我的阿勒泰》逐渐悟到一个道理,返璞归真也是一种美,没必要每个人的人生三十年的年华,都去追求房子,车子等逐渐贬值的东西。人究竟应该追求怎样的一种活法? 什么是城市化?这是我听到的最好…

UniApp 2.0可视化开发工具:引领前端开发新纪元

一、引言 在移动互联网迅猛发展的今天,移动应用开发已经成为前端开发的重要方向之一。为了简化移动应用开发流程,提高开发效率,各大开发平台不断推出新的工具和框架。UniApp作为一款跨平台的移动应用开发框架,自诞生以来就备受开…

山东大学软件学院项目实训-创新实训-基于大模型的旅游平台(十八)- JUC(4)

线程安全分析 成员变量和静态变量是否线程安全? 如果它们没有共享,则线程安全 如果它们被共享了,根据它们的状态是否能够改变,又分两种情况 如果只有读操作,则线程安全如果有读写操作,则这段代码是临界区…

Java之设计模式

概述 设计模式就是经过我们开发人员通过长时间的开发实践得出的一种开发模式,目的就是在开发过程中降低代码耦合度,提高代码可复用性/扩展/维护。目前主要有23种设计模式,分为创建型模式、行为型模式、结构型模式。本文列举了实际项目中使用到的设计模式,包括单例模式、策略模…

分布式和集群区别

分布式 分布式的主要工作是分解任务,将职能拆解,多个人在一起做不同的事 集群 集群主要是将同一个业务,部署在多个服务器上 ,多个人在一起做同样的事

GPT-3:自然语言处理的预训练模型

自然语言处理(NLP)领域近年来取得了显著的进步,特别是预训练模型的引入,彻底改变了我们与计算机交互和处理自然语言的方式。在这些模型中,GPT-3(Generative Pre-trained Transformer 3)无疑是最…