学习Flask之五、数据库
数据库有组织的存贮应用数据。根据需要应用发布查询追踪特定部分。网络应用最常用的数据库是基于关系模式的,也称为SQL数据库,引用结构化查询语句。但是近年来,面向文档和键值的数据库,非正式的统称为NoSQL数据库,成了流行的选择。
SQL 数据库
关系数据库将数据存贮在表里,在应用域内建模不同的实体。例如,订单管理应用的数据库可能用客户,产品,订单表。一个表有一个固定数量的列和可变数量的行。列定义数据的属性。例如,客户表的列可能有姓名,地址,手机号,等。每行定义一个实际的数据要素包含所有的列。表中有特殊的列称为主键,存贮表中各行的单一的标识。表中也可以有称为外键的列,它从相同或不同的表中引用主键。行与行之间的这种链接称为关系,是关系数据模型的基础。
Figure 5-1展示一个简单数据库的图,有两个表存贮用户和用户角色。连接两个表的连线表示两个表的关系。
Figure 5-1. 关系数据库示例
在这个关系数据库图中,角色表存贮所有可能的用户角色,每个角色有唯一的id值--即表的主键。用户表包含用户的列表,每个用户也有唯一的id。除了id主键,角色表有姓名列和用户表有用户名和密码列。用户表中的role_id列是一个外键引用角色id,这样建每个用户的角色。从这个例子可以看到,关系数据库可以有效的存贮数据避免重复。重命名数据库中的用户角色很简单因为角色名存在于一个简单的位置。角色名后跟着改变的角色表,所有的用户有一个role_id引用改变的角色将更新。另一方面,将数据分割成多个表是复杂的。形成带有角色的用户的列表会有一个问题,因为用户和用户角色需要从两个表中读取,需要合并才能呈现。当需要时关系数据库引擎支持表之间的合并操作。
NoSQL数据库
不遵照前面描述的关系模型的数据库统称为NoSQL数据库。NoSQL数据库一个常见的组织使用集合而不是表,使用文档而不是记录。NoSQL数据库的设计使合并操作困难,所以大部分NoSQL数据库不支持合并操作。对于 Figure 5-1的NoSQL数据库结构,列出用户和它们的角色需要进行合并操作,通过读每个用户的role_id,然后从角色表中找到它。
Figure 5-2. NoSQL 数据库示例
更合适的NoSQL数据库的设计见Figure 5-2。这是应用一种称为denormalization的操作的结果。它减少了表的数量但是多了数据的重复。这种结构的数据库的每一个用户都有明文的用户角色名。重命名一个角色是非常复杂的操作,需要更新大量的文档。但是NoSQL也并不是没有好处。有一定的数据重复可以使查询更快。直接列出用户和角色不需要合并操作。
选择SQL 还是NoSQL数据库?
SQL数据库擅长存贮结构化的数据,以有效的和紧凑的方式。这种数据库较长以保留一致性。非关系数据库放松了一致性的要求,结果有时会出现性能边界。 全面的分析和比较超出了本书的范围。对于小型和中型的应用,SQL和NoSQL的能力都是合适的,实际性能也相似。
Python数据库框架
Python有许多数据库引擎,有开源的也有商业的。Flask不限制使用什么数据库包,所以你可以使用MySQL, Postgres, SQLite, Redis, MongoDB,或 CouchDB,只要你喜欢。
因为这些不是足够的选择,还是一些数据库抽像层包如 SQLAlchemy或MongoEngine,它们允许你在更高一层用正常的python对象而不是数据库实体如表,文档或查询语言。 当选择数据库框架时还有一些要评估的因素:
易于使用
当直接比较数据库引擎和数据库抽像层时,每二组明显胜出。抽像层也称为 object-relational mappers(ORMs) 或object-document mappers (ODMs), 提供了高层的面向对象的操作到底层数据库指令的透明的转换。
性能
ORMs和ODMs的转换需要从对象域转换为数据库域,存在一定的开销。大部分情况下性能惩罚是可以忽略的,但并不总是这样。通常,ORMs 和ODMs的生产力超过了性能下降,所以完全抛开ORMs和ODMs不是很合理。合理的是选择数据库抽象层,能提供对数据库的可选的访问,当特定的操作需要通过原始数所库指令优化时。
移植性
需要考虑开发和生产平台的数据库。例如,如果你想将你的应用布局于云平台,你要找到这种服务有什么样的数据库选项。另一种移植方面适用于ORMs 和ODMs。虽然有些框架提供一个数据库引擎的抽像层,别的抽像更高并提供数据库引擎--用相同的面向对象的接口访问。最好的例子是SQLAlchemy ORM,支持关系数据库引擎包括流行的MySQL,Postgres,和SQLite。
Flask集成
选择与Flask集成的框架不是绝对要求的,但是这样中减少你自已写集成代码的工作。
Flask集成可以简化配置和操作,所以使用特殊设计的包作为Flask扩展是很好的选择。因为这些目的,本书选择的数据库框架是Flask-SQLAlchemy,是打包SQLAlchemy的Flask扩展。
用Flask-SQLAlchemy 管理数据库
Flask-SQLAlchemy是Flask扩展,可以简化SQLAlchemy在Flask应用内的使用。SQLAlchemy是强大的关系数据库框架,支持多种数据库后端。它提供高层的 ORM 和底层的访问数据库原生SQL的功能。像大部分其它的扩展一样,Flask-SQLAlchemy通过pip安装。
(venv) $ pip install flask-sqlalchemy
在Flask-SQLAlchemy, 数据库通过URL指明。Table 5-1 列出了三种最常见的数据库引擎的URLs格式。见http://www.aluoyun.cn/details.php? article_id=196
在这些URLs里, hostname指的是提供MySQL服务的服务器,可以是localhost或远程服务器。数据库服务器可以安装多种数据库,所以database指明所有的数据库名。对于需要授权的数据库, username和password是 用户的资格证书。SQLite数据库没有服务器,所以 hostname, username, 和password是忽略的。 database 是磁盘文件名。
应用数据数的URL必须以键SQLALCHEMY_DATABASE_URI在Flask配置对象里配置。另一个有用的选项是配置键SQLALCHEMY_COMMIT_ON_TEARDOWN,它可以设置为True 以使能自动化提交数据库的更改,在每次请求结束。其它配置信息见Flask-SQLAlchemy文档。
Example 5-1如何初始化为配置简单的SQLite数据库
Example 5-1. hello.py: 数据库配置
from flask.ext.sqlalchemy import SQLAlchemy
basedir = os.path.abspath(os.path.dirname(__file__))
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] =\
'sqlite:///' + os.path.join(basedir, 'data.sqlite')
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True
db = SQLAlchemy(app)