数据库按照一定规则保存程序数据,程序再发起查询取回所需的数据。
Web 程序最常用基于关系模型的数据库,这种数据库也称为 SQL 数据库,因为它们使用结构化查询语言。
不过最近几年文档数据库和键值对数据库成了流行的替代选择,这两种数据库合称 NoSQL数据库。
SQL数据库
关系型数据库把数据存储在表中,表模拟程序中不同的实体。
例如,订单管理程序的数据库中可能有表 customers、products 和 orders。
表的列数是固定的,行数是可变的。
- 列定义表所表示的实体的数据属性。
例如,customers 表中可能有 name、address、phone 等列。 - 表中的行定义各列对应的真实数据。
表中有个特殊的列,称为 主键,其值为表中各行的唯一标识符。
表中还可以有称为 外键 的列,引用同一个表或不同表中某行的主键。行之间的这种联系称为关系,这是关系型数据库模型的基础。
下图展示了一个简单数据库的关系图。这个数据库中有两个表,分别存储用户和用户角
色。连接两个表的线代表两个表之间的关系。
在这个数据库关系图中:
roles 表存储所有可用的用户角色,每个角色都使用一个唯一的 id 值(即表的主键)进行标识。
users 表包含用户列表,每个用户也有唯一的 id 值。除了 id 主键之外,roles 表中还有 name 列,users 表中还有 username 列和 password 列。
users表中的 role_id 列是外键,引用角色的 id,通过这种方式为每个用户指定角色。
从这个例子可以看出, 关系型数据库存储数据很高效,而且避免了重复。
将这个数据库中的用户角色重命名也很简单,因为角色名只出现在一个地方。一旦在 roles 表中修改完角色名,所有通过 role_id 引用这个角色的用户都能立即看到更新。
NoSQL数据库
NoSQL 数据库一般使用集合代替表,使用文档代替记录。
NoSQL 数据库采用的设计方式使联结变得困难,所以大多数数据库根本不支持这种操作。
NoSQL 数据库更适合设计成如图所示的结构。这是执行反规范化操作得到的结果,它
减少了表的数量,却增加了数据重复量。
这种结构的数据库要把角色名存储在每个用户中。如此一来,将角色重命名的操作就变得很耗时,可能需要更新大量文档。
使用 NoSQL 数据库当然也有好处。数据重复可以提升查询速度。列出用户及其角色的操作很简单,因为无需联结。
使用SQL还是NoSQL
SQL 数据库擅于用高效且紧凑的形式存储结构化数据。这种数据库需要花费大量精力保证数据的一致性。
NoSQL 数据库放宽了对这种一致性的要求,从而获得性能上的优势。
对中小型程序来说,SQL 和 NoSQL 数据库都是很好的选择,而且性能相当。
Python数据库框架
大多数的数据库引擎都有对应的 Python 包,包括开源包和商业包。
Flask 并不限制你使用何种类型的数据库包,因此可以根据自己的喜好选择使用 MySQL、Postgres、SQLite、Redis、MongoDB 或者 CouchDB。
如果这些都无法满足需求,还有一些数据库抽象层代码包供选择,例如 SQLAlchemy 和MongoEngine。你可以使用这些抽象包直接处理高等级的 Python 对象,而不用处理如表、文档或查询语言此类的数据库实体。
选择数据库框架时,你要考虑很多因素:
1、易用性
如果直接比较数据库引擎和数据库抽象层,显然后者取胜。抽象层,也称为对象关系映射(Object-Relational Mapper,ORM)或对象文档映射(Object-Document Mapper,
ODM),在用户不知觉的情况下把高层的面向对象操作转换成低层的数据库指令。
2、性能
ORM 和 ODM 把对象业务转换成数据库业务会有一定的损耗。大多数情况下,这种性能的降低微不足道,但也不一定都是如此。一般情况下,ORM 和 ODM 对生产率的提升远远超过了这一丁点儿的性能降低,所以性能降低这个理由不足以说服用户完全放弃ORM 和 ODM。
真正的关键点在于如何选择一个能直接操作低层数据库的抽象层,以防特定的操作需要直接使用数据库原生指令优化。
3、可移植性
选择数据库时,必须考虑其是否能在你的开发平台和生产平台中使用。
例如,如果你打算利用云平台托管程序,就要知道这个云服务提供了哪些数据库可供选择。
可移植性还针对 ORM 和 ODM。尽管有些框架只为一种数据库引擎提供抽象层,但其他框架可能做了更高层的抽象,它们支持不同的数据库引擎,而且都使用相同的面向对
象接口。SQLAlchemy ORM 就是一个很好的例子,它支持很多关系型数据库引擎,包
括流行的 MySQL、Postgres 和 SQLite。
4、FLask集成度
选择框架时,你不一定非得选择已经集成了 Flask 的框架,但选择这些框架可以节省你编写集成代码的时间。
使用集成了 Flask 的框架可以简化配置和操作,所以专门为 Flask 开发的扩展是你的首选。
使用Flask-SQLAlchemy管理数据库
Flask-SQLAlchemy 是一个 Flask 扩展,简化了在 Flask 程序中使用 SQLAlchemy 的操作。
SQLAlchemy 是一个很强大的关系型数据库框架,支持多种数据库后台。SQLAlchemy 提供了高层 ORM,也提供了使用数据库原生 SQL 的低层功能。
(venv) $ pip install flask-sqlalchemy
在 Flask-SQLAlchemy 中,数据库使用 URL 指定。最流行的数据库引擎采用的数据 URL格式如下表所示。
FLask-SQLAlchemy数据库URL
数据库引擎 | URL |
---|---|
MySQL | mysql://username:password@hostname/database |
Postgres | postgresql://username:password@hostname/database |
SQLite(Unix) | sqlite:absolute/path/to/database |
SQLite(Windows) | sqlite:///c:/absolute/path/to/database |
在这些 URL 中,hostname 表示 MySQL 服务所在的主机,可以是本地主(localhost),也可以是远程服务器。
数据库服务器上可以托管多个数据库,因此 database 表示要使用的数据库名。如果数据库需要进行认证,username 和 password 表示数据库用户密令。
使用举例:
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:rootpwd@127.0.0.1:3306/database_name?charset-utf8'
SQLite 数据库不需要使用服务器,因此不用指定 hostname、usernam