扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
通过提供用于操作数据库表的类和对象,对象关系映射工具有助于提高生产率。Python 最好的对象关系映射工具是 SQLObject —— 一个开放源码项目,它几乎完成编程数据库所需的所有操作。本文介绍 SQLObject 及其功能。阅读本文后,您将能够不编写任何 SQL 代码而连接 Python 与数据库。
当面向对象编程范例满足大多数数据库的关系范例时,通常会看到对象关系映射。对象关系映射是这两个世界的桥梁。它允许您定义与数据库表对应的类。然后您可以使用这些类及其实例上的方法来与数据库交互,而不用编写 SQL。使用对象关系映射并不意味着不需要知道关系数据库如何工作,而是不必要编写 SQL,从而避免编程错误。
您可以找到一打以上的操作 SQL 数据库的开放源码 Python 包,这还没包括用于连接 Python 与特定数据库的特殊用途模块。SQLObject 是其中最好的模块。它是简单易用的完全对象关系映射包。SQLObject 几乎可以完成编程数据库所需的所有操作。
本文展示了 SQLObject 如何与数据库交互,如何使用 SQLObject 编写数据库访问和数据验证代码,以及如何将它用于遗留或现有数据库。这里假设您已经具备 Python 和关系数据库的知识。
SQLObject 具有一个 setup.py 文件,安装方式与其他任何 Python 包一样。如果您使用的是 Python V2.2,则还需要安装 mxDateTime
Python 包(SQLObject 使用 Python V2.3 的内置 datetime
模块,如果该模块可用的话)。
要实际使用 SQLObject,需要设置数据库包以及这种数据库的 Python 接口。SQLObject 连接多种数据库,其中包括三个大的开放源码产品:MySQL、PostgreSQL 和无服务器 SQLite。
最后,需要为应用程序创建数据库。对于 SQLite,这意味着创建一个存储该数据库的文件。对于其他数据库,这意味着连接数据库服务器,执行 CREATE DATABASE
命令,并授权数据库用户对新数据库的一些访问,以便 SQLObject 可以使用该用户帐户来连接。
清单 1 展示了如何用 MySQL 创建新数据库。
|
需要编写的第一个 Python 代码是数据库连接代码。基于所使用的数据库,这是惟一需要编写不同代码的地方。
例如,如果想让应用程序使用 SQLite 数据库,则需要将数据库文件的路径写入位于 sqlobject.sqlite
包的 SQLite 连接构建器中。如果数据库文件不存在,QLObject 将告诉 SQLite 创建一个,代码如下:
|
如果使用的是 MySQL 或带有服务器的其他数据库,则将数据库连接信息传递到连接构建器中。清单 2 提供了在上一节创建的 MySQL 数据库的示例。
|
不管连接哪种数据库,连接代码都应该放置在一个名称类似 Connection.py 的文件中,且该文件存储在一些通常可访问的位置中。这样,可以导入您定义的所有类,并使用已经构建的 conn
对象。conn
变量将包含所有与数据库相关的详细信息。
但是要注意,SQLObject 的一些特性不可用于 SQLite 或 MySQL。不能将数据库选择与连接之后编写的代码完全分离。(参阅 Using SQLObject with pre-existing tables 获得更多信息。)
SQLObject 使得操作数据库表变得容易。看第一个简单的例子,考虑一个电话簿应用程序的由单个表组成的数据库模式,如表 1 所示。
字段 | 类型 | 说明 |
id |
Int | 主键 |
number |
String | “(###) ###-####”字符串格式;应该惟一 |
owner |
String | 这是谁的号码? |
last_call |
Date | 用户最后一次呼叫该号码是什么时候? |
取决于您的 SQL 风格,该表的 SQL 类似如下:
|
使用 SQLObject,不需要编写该 SQL 代码。通过定义 Python 类来定义该数据表。该代码将进入名为 PhoneNumber.py 的文件中,如清单 3 所示。
|
在此使用了先前定义的 conn
变量。每个表类需要将对数据库连接的引用存储在它的 _connection
成员中。该信息隐式用于对该类的表的所有数据库访问中。因此,不必担心 SQL 或任何特殊数据库,因为代码可以按照抽象关系模式来表示。
定义表的类还有一组定义表字段的成员。SQLObject 提供了 StringCol
、BoolCol
等等 —— 一个类对应一种数据库字段类型。
createTable()
方法第一次运行时,SQLObject 将创建一个名为 phone_number
的表。然后,它将只使用该表,因为您将 ifNotExists
设置为 True
来调用该方法。
最后注意,无需在 PhoneNumber
中为 id
字段创建字段对象。因为 SQLObject 总是需要该字段对象,所以它总会创建一个。
著名的缩写词 CRUD 代表对数据库行进行的四种操作:Create、Read、Update 和 Delete。定义了与数据库表对应的类之后,SQLObject 将对表行的操作表示为对类及其实例的操作。
要创建数据库行,需创建对应类的实例,代码如下:
|
现在 phone_number
表有一个存储我的姓名的行。PhoneNumber
构造函数将表列的值作为关键字参数。它使用您提供的数据创建一行 phone_number
。如果由于某种原因,数据不能进入数据库,则构造函数抛出一个异常。当电话号码无效时,会发生如下情况:
|
如果电话号码已经在数据库中,将会看到:
|
SQLObject 类的实例的所有字段可用作成员。这与其他一些将数据库行当作字典的数据库映射工具相反。因此,对于数据库行中的每个字段,PhoneNumber
对象都具有一个成员。
|
但如何检索数据库中已经存在的 PhoneNumber
对象呢?需要对数据库执行查询来获取。这就是 SQLObject 的查询构造工具包(该软件包最有趣的特性之一)发挥作用的地方。它允许将 SQL 查询表示为 Python 对象链。如果您熟悉 Java™ 编程语言的对象关系包的话,它与可以对 Torque 中 Criteria
对象执行的操作一样。
您定义的每个 SQLObject 类都有一个 select()
方法。该方法接受一个定义查询的对象,返回与该查询匹配的项列表。例如,下面这个方法调用返回包含数据库中第一个电话号码的列表:
|
PhoneNumber.q.id
指明想要对 phone_number
表的 id
字段运行查询。SQLObject 过载比较操作符(==
、!=
、<
、>=
等等)来执行除布尔表达式之外的查询。表达式 PhoneNumber.q.id==1
是与 id
字段值为 1 的每行相匹配的查询。更多示例如下:
|
可以使用 SQLObject 的 AND
和 OR
函数来组合查询子句:
|
下列查询获取一年中呼叫过的所有人以及从未呼叫过的所有人:
|
如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。
现场直击|2021世界人工智能大会
直击5G创新地带,就在2021MWC上海
5G已至 转型当时——服务提供商如何把握转型的绝佳时机
寻找自己的Flag
华为开发者大会2020(Cloud)- 科技行者