大多数数据库引擎都有对应的Python包,如:MySQL、SQLite、Redis、MongoDB等。此外还有一些数据库抽象层代码包供选择,如:SQLAlchemy和MongoEngine。选择数据库框架式,要考虑很多因素:
抽象层也成为对象关系映射(ORM)或对象文档映射(ODM),可以把高层的面向对象操作转换为底层的数据库指令。因此,相比数据库引擎,更具易用性。
ORM和ODM把对象转换为数据库业务时会有一定损耗,但它们对生产效率的提升远远超过了这一丁点儿性能的降低。
选择数据库时必须考虑其是否能在你的开发平台和生产平台中使用。可移植性还针对ORM和ODM,有些框架只为一种数据库引擎提供抽象层。但其它框架可能做了更高层的抽象,支持不同的数据库引擎,并使用相同的现象对象接口。如SQLAlchemy ORM支持MySQL/Postgres/SQLite数据库引擎。
使用集成了Flask的数据库框架可以简化配置和操作,《Flask Web开发》一书选择的数据库框架是Flask-SQLAlchemy,这个Flask扩展包装了SQLAlchemy框架。
SQLAlchemy提供了高层ORM,也提供了使用数据库原生SQL的底层功能,Flask-SQLAlchemy的安装:
pip install flask-sqlalchemy
Flask-SQLAlchemy数据库URL
数据库引擎 | URL |
MySQL | mysql://username:password@hostname/database |
Postgres | postgresql://username:password@hostname/database |
SQLite(Linux/macOS) | sqlite:////absolute/path/to/database |
SQLite(Wondows) | sqlite:///c:/absolute/path/to/database |
SQLite数据库没有服务器,因此不用指定hostname/passwordd/username,URL中的database是磁盘中的文件名。 应用使用的数据库URL保存在Flask配置对象的SQLALCHEMY_DATABASE_URI键中。Flask-SQLAlchemy建议把SQLALCHEMY_TRACK_MODIFICATIONS键设为False,以便在不需要跟踪对象变化时降低内存消耗。
app.py 配置数据库:
import os
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
# 配置SQLite数据库
basedir = os.path.abspath(os.path.dirname(__file__))
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir, 'data.sqlite')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
db对象是SQLAlchemy类的实例,表示应用使用的数据库。
模型表示应用使用的持久化实体。在ORM中模型为一个Python类,类中的属性对应于数据库表中的列。Flask-SQLAlchemy提供了创建数据库实例的基类以及一系列辅助类和辅助函数,用于定义模型的结果。
app.py 添加模型定义:
class Role(db.Model):
"""定义角色模型"""
__tablename__ = 'roles'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(64), unique=True)
# 关联的另一端是哪个模型
users = db.relationship('User', backref='role')
def __repr__(self):
return '' % self.name
class User(db.Model):
"""定义用户模型"""
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(64), unique=True, index=True)
role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))
def __repr__(self):
return '' % self.username
说明:
表5-2 最常用的SQLAlchemy列类型
类型名 | Python类型 | 说明 |
Integer | int | 普通整数,32位 |
SmallInteger | int | 取值范围小的整数,16位 |
BigInteger | int 或 long | 不限制精度的整数 |
Float | float | 浮点数 |
Numeric | decimal.Decimal | 定点数 |
String | str | 变长字符串 |
Text | str | 变长字符串,对较长或不限长度的字符串坐了优化 |
Unicode | unicode | 变长Unicode字符串 |
UnicodeText | unicode | 变长Unicode字符串,对较长或不限长度的字符串坐了优化 |
Boolean | boolean | 布尔值 |
Date | datetime.date | 日期 |
Time | datetime.time | 时间 |
DateTime | datatime.datetime | 日期和时间 |
Interval | datetime.timedelta | 时间间隔 |
Enum | str | 一组字符串 |
PickleType | 任何python对象 | 自动使用Pickle序列化 |
LargeBinary | str | 二进制blob |
表5-3 最常用的SQLAlchemy列选项
选项名 | 说明 |
primary_key | True:列为表的主键 |
unique | True:列为不允许出现重复的值 |
index | True:为列创建索引,提升查询效率 |
nullable | True:列允许使用空值;False:列不允许使用空值 |
default | 为列定义默认值 |
关系数据库使用关系把不同表中的行关联起来。关联关系包含:一对一/一对多(使用外键关联)/多对多(使用第三张表,关系表来实现)。如上述app.py定义的模型就实现了roles和users的一对多关系:
class Role(db.Model):
"""定义角色模型"""
...
# 关联的另一端是哪个模型
users = db.relationship('User', backref='role')
class User(db.Model):
"""定义用户模型"""
...
role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))
表5-4 常用的SQLAlchemy关系选项
选项名 | 说明 |
backref | 在关系的另一个模型中添加反向引用 |
uselist | 设为False,表示不使用列表,使用标量值(一对一关系) |
secondary | 多对多关系中关联表的名称 |
order_by | 关系中记录的排序方式 |
primaryjoin | 指定2个模型间使用的联结条件,只在模棱两可的关系中指定 |
secondaryjoin | SQLAlchemy无法自行决定时,指定多对多关系中的二级联结条件 |
lazy | 指定如何加载相关记录,可选值:
|