前言
数据库按照一定规则保存程序数据,程序再发起查询取回所需的数据。Web程序最常用基于关系模型的数据库,这种数据库也称为SQL数据,因为它们使用结构化查询语句。不过最近几年文档数据库和键值对数据库成了流行的替代选择,这两种数据库合称为NoSQL数据库。
大多数的数据库引擎都有对应的Python包,包括开源宝和商业包。Flask并不限制你使用何种类型的数据库包,因此可以根据自己的喜好选择使用MySQL、Postgres、SQLite,Redis、MongoDB或者CouchDB。
如果这些都无法满足需求,还有一些数据库抽象层代码包供选择,例如SQLAlchemy和MongoEngine。你可以使用这些抽象包直接处理高等级的Python对象,而不用处理如表、文档或查询语言此类的数据库实体。
选择框架时,你不一定非得选择已经集成了Flask的框架,但选择这些框架可以节约你编写集成代码的时间。使用集成了Flask的框架可以简化配置和操作,所以专门为Flask开发的扩展是你的首选。
关于选择使用的数据库框架,选择的是Flask-SQLAlchemy。
安装Flask-SQLAlchemy
1 | sudo pip install flask-sqlalchemy |
配置
在Flask-SQLAlchemy中,数据库使用URL指定。1
2
3MySQL : mysql://username:password@hostname/database
Postgres : postgresql://username:password@hostname/database
SQLite : sqlite:////absolute/path/to/database
程序使用的数据库URL必须保存到Flask配置对象的SQLALCHEMY_DATABASE_URI键中。配置对象中还有一个很有用的选项,即SQLALCHEMY_ON_REARDOWN键,将其设置为True时,每次请求结束后都会自动提交数据库中的变动。
我们使用SQLite数据库,配置代码 如下:1
2
3
4
5
6
7
8
9
10
11
12from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
import os
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)
定义模型
定义一个用户表users和一个角色表roles,代码如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16class User(db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer,primary_key=True)
username = db.Column(db.String(64),unique=True,index=True)
def __repr__(self):
return '<User %r>' % self.username
class Role(db.Model):
__tablename__ = 'roles'
id = db.Column(db.Integer,primary_key=True)
name = db.Column(db.String(64),unique=True)
def __repr__(self):
return '<Role %r>' % self.name
解释:1
2
30.两个类User和Role继承自db.Model
1.__tablename__用来指定表名称
2.db.Column函数指定了数据库中字段的类型,是否是主键(primary_key),是否唯一(unique),是否加索引(index),还有其他的比如:是否可以为空(nullable=True),默认值(default)
关系
使用关系型数据库,不指定关系怎么能行。定义模型中我们没有指定关系,一个用户有一个角色,一个角色可以属于多个用户,典型的一对多的关系,如何在Flask-SQLAlchemy中定义关系?1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21class 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 '<User %r>' % self.username
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 '<Role %r>' % self.name
添加了两行代码:
第一行:1
role_id = db.Column(db.Integer,db.ForeignKey('roles.id'))
这句话比较好理解,和上面普通变量差不多,就是User类中添加了一个role_id变量,数据类型db.Integer,第二个参数指定外键是哪个表中哪个id。
第二行:1
users = db.Relationship('User',backref='role')
1 | 0.添加到Role模型中的users属性代表这个关系的面向对象视角。对于一个Role类的实例,其users属性将返回与角色相关联的用户组成的列表。 |
数据库操作
创建数据库和表
1 | db.create_all() |
删除数据库
1 | db.drop_all() |
插入行
1 | role_admin = Role(name='Admin') |
通过数据库会话管理对数据库所做的改动,在Flask-SQLAlchemy中,会话由db.session表示,准备把队形写入数据库之前,先要将其添加到会话中。写入数据库需要调用db.session.commit()方法。
修改行
我们将role_admin变量中name为Admin改成Administrator1
2
3role_admin.name='Administrator'
db.session.add(role_admin)
db.session.commit()
删除行
1 | db.session.delete(user_jim) |
查询行
查询所有用户1
User.query.all() #返回结果:[<User 'tom'>, <User 'tim'>, <User 'sam'>]