python - 如何解析 JSON 模式文件并使用许多列约束动态创建新的 Python 类?
问题描述
我将 SQLAlchemy 1.4 ORM 与 postgres13 和 Python 3.7 一起使用。
为清晰和完善而编辑:
为了建立项目并对其进行测试,这 3 个文件运行良好:
base.py
--> 设置 SQLAlchemy 引擎和数据库会话
models.py
--> 一个用户类被定义了一些字段
inserts.py
--> 创建用户类的实例,添加并提交到数据库
models.py
如果已经定义了硬编码的类(例如用户类),这一切都很好。
我有一个schema.json
定义数据库模式的文件。该文件非常大,包含许多嵌套字典。目标是解析 json 文件并使用给定的模式在models.py
(或任何文件)中自动创建 Python 类。
一个例子schema.json
:
"groupings": {
"imaging": {
"owner": { "type": "uuid", "required": true, "index": true },
"tags": { "type": "text", "index": true }
"filename": { "type": "text" },
},
"user": {
"email": { "type": "text", "required": true, "unique": true },
"name": { "type": "text" },
"role": {
"type": "text",
"required": true,
"values": [
"admin",
"customer",
],
"index": true
},
"date_last_logged": { "type": "timestamptz" }
}
},
"auths": {
"boilerplate": {
"owner": ["read", "update", "delete"],
"org_account": [],
"customer": ["create", "read", "update", "delete"]
},
"loggers": {
"owner": [],
"customer": []
}
}
}
模型的类需要通过解析 json 来动态创建,因为模式将来可能会发生变化,并且每次手动硬编码 100 多个类无法扩展。
我花了很多时间研究这个,但还没有找到一个完全成功的解决方案。目前这就是我处理解析和动态表创建的方式。
我有这个函数create_class(table_data)
,它传递了一个已经解析过的字典,其中包含所有表名、列名、列约束。问题是,我无法弄清楚如何创建带有约束的表。目前,运行此代码会将表提交到数据库,但就列而言,它仅采用从 Base 继承的内容(自动生成的 PK ID)。
写入constraint_dict 的所有列名和约束都将被忽略。
该行#db_session.add(MyTableClass)
被注释掉,因为它错误“sqlalchemy.orm.exc.UnmappedInstanceError: Class 'sqlalchemy.orm.decl_api.DeclarativeMeta' is not mapped; is a class ( main .MyTableClass) provided where an instance is required?”
我认为这一定与操作顺序有关——我在提交类本身之前创建了一个类的实例。我意识到这进一步混淆了事情,因为我实际上并没有调用 MyTableClass。
def create_class(table_data):
constraint_dict = {'__tablename__': 'myTableName'}
for k, v in table_data.items():
if 'table' in k:
constraint_dict['__tablename__'] = v
else:
constraint_dict[k] = f'Column({v})'
MyTableClass = type('MyTableClass', (Base,), constraint_dict)
Base.metadata.create_all(bind=engine)
#db_session.add(MyTableClass)
db_session.commit()
db_session.close()
return
我不太确定要查看什么来完成将所有列及其约束提交到数据库的最后一步。任何帮助是极大的赞赏!
解决方案
这并不能直接回答您的问题,而是提出了不同的策略。如果您希望 json 数据经常更改,您可以考虑创建一个带有 id 和 data 列的简单模型,本质上使用 postgres 作为 json 文档存储。
from sqlalchemy.dialects.postgresql import JSONB
class Schema(db.Model):
id = db.Column(db.Integer(), nullable=False, primary_key=True, )
data= db.Column(JSONB)
sqlalchemy :posgres 方言 JSONB 类型
JSONB 数据类型比 posgres 中的 JSON 数据类型更可取,因为二进制表示的搜索效率更高,尽管 JSONB 的插入时间确实比 JSON 稍长。您可以在 posgres文档中阅读有关 JSON 和 JSONB 数据类型之间区别的更多信息
这篇 SO 帖子解释了如何使用 SQLAlchemy 在 posgres 中执行 json 操作:sqlalchemy filter by json field
推荐阅读
- sql - 如何仅使用 SQL 合并行?
- google-cloud-tpu - 在谷歌云控制台上打开 tpus 页面时出错
- asp.net-core - 如何使用查询字符串将自定义 url 设置为操作路由 .net 核心
- objective-c - 是否可以使用 VImage 检查两个捕获的帧之间的差异?
- android - 列表未使用改造进入 recyclerview
- c++ - 如何 CMake 将库编译为我的应用程序源的一部分,而不是作为静态/共享库?
- python - 我无法使用 pip 版本 19.2.3 安装任何软件包
- flutter - Fluter Bloc 从网格中删除项目
- python - 从线程内部发送消息时出现discord.py错误
- amcharts - Amchart 3根据xaxis值绘制水平线