讲数据库操作了
创建表
首先,我们要让Flask-SQLAlchemy 根据模型类创建数据库。方法是使用db.create_all()
函数:
(venv) $ python hello.py shell
>>> from hello import db
>>> db.create_all()
插入行
下面这段代码创建了一些角色和用户:
>>> from hello import Role, User
>>> admin_role = Role(name='Admin')
>>> mod_role = Role(name='Moderator')
>>> user_role = Role(name='User')
>>> user_john = User(username='john', role=admin_role) #User类虽然没有role属性,但是在上一章节里面的Role里面设置了一个backref属性,就是用来反向作用的。
>>> user_susan = User(username='susan', role=user_role) #注意啊,这里的role=user_role针对的是上一章节里面说的,对应的是模型对象!不是键的值!!!
>>> user_david = User(username='david', role=user_role)
模型的构造函数接受的参数是使用关键字参数指定的模型属性初始值。注意,role 属性也可使用,虽然它不是真正的数据库列,但却是一对多关系的高级表示。这些新建对象的id属性并没有明确设定,因为主键是由Flask-SQLAlchemy 管理的。现在这些对象只存在于Python 中,还未写入数据库。因此id 尚未赋值:
>>> print(admin_role.id)
None
>>> print(mod_role.id)
None
>>> print(user_role.id)
None
通过数据库会话管理对数据库所做的改动,在Flask-SQLAlchemy 中,会话由db.session表示。准备把对象写入数据库之前,先要将其添加到会话中:
>>> db.session.add(admin_role)
>>> db.session.add(mod_role)
>>> db.session.add(user_role)
>>> db.session.add(user_john)
>>> db.session.add(user_susan)
>>> db.session.add(user_david)
或者简写成
db.session.add_all([admin_role, mod_role, user_role,
... user_john, user_susan, user_david])
这里的session首先是和前面章节讲的HTTP里面的session不一样的
不过我感觉作用是类似的,相当于一个缓存的作用,把实例化生成的对象存放在session里面
最后通过commit命令执行保存在数据库内。
db.session.commit()
接着,再去查看属性,已经有了
>>> print(admin_role.id)
1
>>> print(mod_role.id)
2
>>> print(user_role.id)
3
修改行
在数据库会话上调用add() 方法也能更新模型。我们继续在之前的shell 会话中进行操作,下面这个例子把"Admin" 角色重命名为"Administrator":
>>> admin_role.name = 'Administrator'
>>> db.session.add(admin_role)
>>> db.session.commit()
删除行
数据库会话还有个delete() 方法。下面这个例子把"Moderator" 角色从数据库中删除:
>>> db.session.delete(mod_role)
>>> db.session.commit()
查询行
Flask-SQLAlchemy 为每个模型类都提供了query 对象。最基本的模型查询是取回对应表中
的所有记录:
>>> Role.query.all()
[<Role u'Administrator'>, <Role u'User'>]
>>> User.query.all()
[<User u'john'>, <User u'susan'>, <User u'david'>]
使用过滤器可以配置query 对象进行更精确的数据库查询。下面这个例子查找角色为"User" 的所有用户:
>>> User.query.filter_by(role=user_role).all()
[<User u'susan'>, <User u'david'>]
filter_by()等过滤器在query 对象上调用,返回一个更精确的query 对象。多个过滤器可以一起调用,直到获得所需结果。
关系和查询的处理方式类似。下面这个例子分别从关系的两端查询角色和用户之间的一对多关系:
>>> users = user_role.users
>>> users
[<User u'susan'>, <User u'david'>]
>>> users[0].role
<Role u'User'>
这个例子中的user_role.users 查询有个小问题。执行user_role.users 表达式时,隐含的查询会调用all() 返回一个用户列表。query 对象是隐藏的,因此无法指定更精确的查询
过滤器。就这个特定示例而言,返回一个按照字母顺序排序的用户列表可能更好。在示例5-4 中,我们修改了关系的设置,加入了lazy = 'dynamic' 参数,从而禁止自动执行查询。
示例5-4 hello.py:动态关系
class Role(db.Model):
# ...
users = db.relationship('User', backref='role', lazy='dynamic')
# ...
这样配置关系之后,user_role.users 会返回一个尚未执行的查询,因此可以在其上添加过
滤器:
>>> user_role.users.order_by(User.username).all()
[<User u'david'>, <User u'susan'>]
>>> user_role.users.count()
2
我的理解是,通过添加lazy参数后,他生成的对象就是不直接显示内容,而是要通过过滤器才能显示的。