未加星标

Openstack_SQLAlchemy_一对多关系表的多表插入实现

字体大小 | |
[开发(python) 所属分类 开发(python) | 发布者 店小二05 | 时间 2016 | 作者 红领巾 ] 0人收藏点击收藏
目录 Openstack 与 SQLAlchemy

SQLAlchemy 是 python 语言下的一款开源软件,它提供了 SQL 工具包以及对象关系映射器(ORM)。SQLAlchemy 主要分为两个部分: SQLAlchemy Core 和 SQLAlchemy ORM 。

前者包括了 SQL 语言表达式/数据引擎/连接池等 , 主要实现了:连接不同类型的数据库,提交查询和更新请求,定义数据库数据类型和定义 Schema 等功能。 后者提供了数据映射模式,将程序中的 对象数据 映射成数据库中的 关系数据 。但不可避免的会因为 映射 而降低程序效率。

SQLAlchemy 最大的好处在于,当数据从一中数据库管理器系统迁移到另外一种数据库管理系统时(EG. mysql > PostgreSQL),Python 程序员可以不用修改或者修改少量配置文件后仍能正常运行。所以 SQLAlchemy 是 Python 语言中较为常用的一款数据库 ORM 工具,也是 Openstack 默认支持 ORM 工具。

本篇主要记录了,我们如何对数据库中 一对多 的关系表进行多表插入。

一个多表插入的 Demo

在这个 Demo 中定义了 Table: virtual_machines 和 Table: datastores 。这两个实体对象之间的关系为: 一个 VirtualMachine 可以对应拥有多个 Datastore 。

Step 1: 在数据库初始化模块中中定义 Table virtual_machines 和 datastores # octopunch/octopunch/db/sqlalchemy/migrate_repo/versions/001_octopunch_init.py def define_tables(meta): virtual_machines = Table( 'virtual_machines', meta, Column('uuid', String(length=45), primary_key=True, nullable=False), Column('vm_value', String(length=255)), Column('name', String(length=255)), mysql_engine='InnoDB' ) datastores = Table( 'datastores', meta, Column('uuid', String(length=45), primary_key=True, nullable=False), Column('ds_value', String(length=255)), Column('name', String(length=255)), Column('virtual_machine_uuid', String(length=45), ForeignKey('virtual_machines.uuid')), mysql_engine='InnoDB' )

NOTE: Table datastores 的外键值为 virtual_machines 的主键值

Step 2:在 SQLAlchemy 的 models 模块中定义对应的 class ,并且将它们之间的关系设定为为一对多的关系

数据库二维表中的一行记录成为了一个类,一个字段成为了一个类属性

# octopunch/octopunch/db/sqlalchemy/models.py class VirtualMachine(BASE, OctopunchBase): """Represents the virtual machine list.""" __tablename__ = 'virtual_machines' uuid = Colmn(String(45), primary_key=True, primary_key=True) vm_value = Column(String(255)) name = Column(String(255)) datastores = relationship('Datastore', backref='virtual_machines', foreign_keys='Datastore.virtual_machine_uuid', primaryjoin='VirtualMachine.uuid ==' 'Datastore.virtual_machine_uuid') class Datastore(BASE, OctopunchBase): """Represents the datastore list.""" __tablename__ = 'datastores' uuid = Colmn(String(45), primary_key=True, primary_key=True) ds_value = Column(String(45)) name = Column(String(255)) virtual_machine_uuid = Column(String(45), ForeignKey('virtual_machines.uuid'))

NOTE:SQLAlchemy 提供的 relationship() 函数用于定义表与表之间的关系,通过参数 foreign_keys 和 backref 指定了 Table virtual_machines 和 datastores 之间的关系为 双向的一对多关系 。

详见: SQLAlchemy_定义(一对一/一对多/多对多)关系

Step 3:定义 SQLAlchemy 的数据库操作接口函数, 这里定义了对 Table virtual_machines 的 create 操作

NOTE:因为我们希望实现多表插入,即一次性插入两张表的数据,所以只要定义对一张表的 SQLAlchemy creae 函数即可。但这一函数必须是对应表示 ‘一’ 的一张表。

EG.Table virtual_machines :

# octopunch/octopunch/db/sqlalchemy/api.py def _resource_refs(resource_dict, resource_class): resource_ref = resource_class() for k, v in resource_dict.items(): resource_ref[k] = v return resource_ref @require_context def virtual_machine_create(context, values): datastores = values.pop('datastores') # 将键值对 'datastores': '...' 中的 Str(datastores) 类型对象替换为 models.Datastore(datastores) 对象 values['datastores'] = [_resource_refs(datastore, models.Datastore) for datastore in datastores] if not values.get('uuid'): values['uuid'] = str(uuid.uuid4()) virtual_machine_ref = models.VirtualMachine() virtual_machine_ref.update(values) # update 类 VirtualMachine 实例对象 virtual_machine_ref 的成员属性值 session = get_session() with session.begin(): session.add(virtual_machine_ref) return virtual_machine_ref

先看看,接口函数 virtual_machine_create(context, values) 中的形参 values 就是要写入到数据库中的数据。 values 是一个 Dict 的数据类型对象。其 key 为数据库表的字段名, value 为字段对应的值。

一般来说,形参 values 的键值对元素和数据库表中的字段是相匹配的,个数也会相同。

但需要注意的是:如果希望对 一对多 或 多对多 的关系表进行多表插入,那么就需要将表示为 ‘多’ 的一方的插入表数据也合并为存放于该 values 中一个键值对元素。

EXAMPLE: Table virtual_machines 的 values 格式

virtual_machine = { 'uuid': '<virtual_machine_uuid>', 'vm_value': '<virtual_machine_value>', 'name': '<virtual_machine_name>', # 必须为 Table datastores 的 table_name 'datastores': '[ { "name": "<datastore_1_name>", ... }, { "name": "<datastore_2_name>", ... }, ... ]' } 为什么只需要按照这样的合适定义 values 就可以实现我们想要的结果呢? 是因为我们在 models 模块定义 class VirtualMachine 和 Datastore 时,指定了两者之间为 双向一对多 的关系,所以 SQLAlchemy 会在 VirtualMachine 中添加 datastores 成员属性。SQLAlchemy 会自动为该属性赋予上述字典中 virtual_machine['datastores'] 的值。

这个动作在语句

virtual_machine_ref.update(values)

处执行。

注意:请回过头在看看 Step 3 的代码实现。

Step 4:为 octopunch.octopunch.db.sqlalchemy.api.virtual_machine_create() 传入 values 的实参

实际上你可以在任何地方,调用并为其传入实参

octopunch.octopunch.db.sqlalchemy.api. virtual_machine_create()

,所以这里就不给出实例代码了。

可以参考: Openstack 通过 SQLAlchemy-ORM 访问数据库

小结

如何通过 SQLAlchemy 为 一对多 关系表进行多表插入?

需要在 models 模块中定义表的类,并指定表之间的关系 定义 SQLAlchemy 的操作接口函数时,只需要定义一张表对应的 create 函数即可 create 函数的形参数 values 的格式遵守上述 EXAMPLE 的格式 在 create 函数中要实例化两张表对应在 models 模块中的类对象

本质上,该 Demo 就是对 SQLAlchemy 的一次 ORM 操作 ―― 将对二维表的操作转化为对类对象操作的方式 。

1. 实例化得到 models 模块中的表类对象。

2. 调用表类对象的 update 函数将需要写入到数据库中的数据更新到表类对象的成员属性值。

3. 创建连接数据库的 session 对象。

4. 调用 session.add() 将表类对象的成员属性值写入到数据库的二维表中。

本文开发(python)相关术语:python基础教程 python多线程 web开发工程师 软件开发工程师 软件开发流程

分页:12
转载请注明
本文标题:Openstack_SQLAlchemy_一对多关系表的多表插入实现
本站链接:http://www.codesec.net/view/485618.html
分享请点击:


1.凡CodeSecTeam转载的文章,均出自其它媒体或其他官网介绍,目的在于传递更多的信息,并不代表本站赞同其观点和其真实性负责;
2.转载的文章仅代表原创作者观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,本站对该文以及其中全部或者部分内容、文字的真实性、完整性、及时性,不作出任何保证或承若;
3.如本站转载稿涉及版权等问题,请作者及时联系本站,我们会及时处理。
登录后可拥有收藏文章、关注作者等权限...
技术大类 技术大类 | 开发(python) | 评论(0) | 阅读(44)