使用flask编写web应用程序时,不可避免的会要使用数据据,特别是关系型数据库mysql。为了简化对数据库的操作,出现在对象关系映射ORM框架。 Flask-SQLAlchemy是基于SQLAlchemy实现的一个插件。
1. 安装
使用命令:
$ pip install flask-sqlalchemy
安装。之后可以初始化flask-sqlalchemy
1
2
3
4
5
6
app = Flask(__name__)
app.config.from_object('app.config')
db = SQLAlchemy()
db.init_app(app)
db.create_all(app=app)
使用flask-sqlalchemy必须要在config里配置SQLALCHEMY_DATABASE_URI。
1
SQLALCHEMY_DATABASE_URI = 'sqlite:///db/users.db'
这里我们使用SQLite3数据库。所以使用’sqlite:///’开头,之后可以使用绝对路径,也可以使用相对路径。绝对路径需要以’/’开头。这里使用的是相对路径, 表示当前目录下db/users.db这个数据库。然后运行程序,可以看到在db目录下有了users.db这个数据库。但是数据库文件里没有任何数据表。
2. 创建数据表模型
通过定义一个继承db.Model的类,便定义了一个模型,这个模型便对应数据库中的一个表。
1
2
3
4
5
6
7
8
9
10
11
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50), unique=True)
age = db.Column(db.Integer)
def __init__(self, name, age):
self.name = name
self.age = age
def __repr__(self):
return '<User %r>' % self.name
之后再运行程序,db.create_all()会同时在数据库users.db里创建一个表user。上面的模型类似于执行下列sql语句。
1
2
3
4
5
6
7
CREATE TABLE user (
id INTEGER NOT NULL,
name VARCHAR(50),
age INTEGER,
PRIMARY KEY (id),
UNIQUE (name)
);
同时,可以使用db.drop_all()这行代码实现删除所有数据表,但是数据库文件users.db会被保留。需要注意的是,必须在db.create_all()调用之前导入 数据表模型才会在数据库中创建数据表。
3. 增删改查
3.1 添加数据
使用下面代码可以往数据库中添加数据:
1
2
3
4
5
6
7
@app.route('/add')
def add():
db.session.add(User('tom', 18))
db.session.add(User('cat', 20))
db.session.commit()
return 'add successfully'
记得要调用db.session.commit()提交事务,不然数据不会放到数据库中。
3.2 查找数据
每个数据模型可以通过query接口从相应表中查询数据,查询user表中所有数据:
1
user = User.query.all()
也可以使用filter_by()方法对查询结果进行过滤:
1
user = User.query.filter_by(name='tom').all()
还可以filter()方法以范围对结果进行过滤:
1
user = User.query.filter(User.age>17).all()
所有的查询结果通过all()全部获取,也可以通过first()只获取第一个。
3.3 更新数据
更新数据可以使用add()更新数据:
1
2
3
4
5
user = User.query.filter_by(name='Tom').first()
if user:
user.age += 1
db.session.add(user)
db.session.commit()
也可以使用update()方法实现更新:
1
2
User.query.filter_by(name='tom').update({'age': User.age+1})
db.session.commit()
同样,更新之后需要使用commit()提交事务。
3.4 删除数据
删除方法和添加方法有些类似,使用delete()方法可以实现:
1
2
3
4
user = User.query.filter_by(name='tom').first()
if user:
db.session.delete(user)
db.session.commit()
4. 一对多模型
在使用MySQL这种关系型数据库时,经常会用到多表连接的情况,SQLAlchemy也提供了这种一对多的模型。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Score(db.Model):
id = db.Column(db.Integer, primary_key=True)
course = db.Column(db.String(50))
access_date = db.Column(db.DateTime)
score = db.Column(db.Float)
name = db.Column(db.String(50))
is_access = db.Column(db.Boolean)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
user = db.relationship('User', backref=db.backref('scores', lazy='dynamic'))
def __init__(self, course, score, user, assess_date=None):
self.course = course
self.score = score
self.is_pass = (score >= 60)
if assess_date is None:
assess_date = datetime.now()
self.name = user.name
self.assess_date = assess_date
# self.user = user
def __repr__(self):
return '<Course %r of User %r>' % (self.course, self.user.name)
Score模型定义的属性中,’user_id’是申明的一个外键,表明了score表和user表之间关联关生活费,’user’并不是数据表中的一个字段,它使用 ‘db.relationship()’方法可以让我们在代码中使用‘Score.user’访问当前score记录的一个对象, 它的第一个参数’User’就表明这个属性使用的对象模 型是’User’。第二个参数’backref‘定义了从User模型反向引用Score模型的方法,我们可以使用’User.scores’获取当前user对象所有的记录。
4.1 添加记录
可以使用如下代码添加记录:
1
2
3
4
5
6
7
8
9
10
@app.route('/score_add')
def score_add():
user = User.query.filter_by(name='tom').first()
if user:
db.session.add(Score('Math', 80.5, user))
db.session.add(Score('Art', 95, user))
db.session.commit()
return 'score add successfully'
可以使用’User.scores’查询某个用户的成绩:
1
2
3
4
5
6
7
8
9
10
@app.route('/score_find')
def score_find():
name = request.args.get('name')
user = User.query.filter_by(name=name).first()
if user:
for score in user.scores:
print('name {}, course: {}, score: {};'.format(score.name, score.course, score.score))
return 'score find successfully'
获取示例代码,请点击这里