1 定义模型python
在 ORM 中,模型通常是一个 Python 类, 表明数据库中的一张表, 类中的属性对应数据库表中的列。Flask-SQLAlchemy 建立的数据库实例为模型提供了一个基类db.Model以及一系列辅助类和辅助函数,可用于定义 模型/表 的结构。下面的例子定义了两个表,一个是用户角色,一个是用户信息sql
db.Column 类构造函数的第一个参数是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 class 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数据库表列/模型属性 的类型
db.Column 中其他的参数指定属性的配置选项
。shell
选项名 | 说 明 |
---|---|
primary_key | 若是设为 True,这列就是表的主键 |
unique | 若是设为 True,这列不容许出现重复的值 |
index | 若是设为 True,为这列建立索引,提高查询效率 |
nullable | 若是设为 True,这列容许使用空值;若是设为 False,这列不容许使用空值 |
default | 为这列定义默认值数据库 |
2 数据库操做ruby
2.1 建立表session
SQLAlchemy 的实现,能够看到 Model 是一个元类,在继承这个类来声明子类的时候,会把表模型注册到 sqlalchemy 里,因此在 create_all 以前必须把模型的声明导入进来, 好比你可能须要这样作from model.account import User,User的定义是def User(db.Model)这样的,好比app
查看程序目录,会发现新建了一个名为app.db的文件。这个 SQLite 数据库文件 的名字就是在配置中指定的。若是数据库表已经存在于数据库中,那么 db.create_all() 不会从新建立或者更新这个表
更新现有数据库表的粗暴方式是先再从新建立:(venv) $ python hello.py shell # 进入 Python shell >>> from hello import db # 从`hello.py`导入建立的数据库实例 >>> db.create_all()删除旧表
这个方法有个咱们不想看到的反作用,它把数据库中了。末尾将会介绍一种称为的方式用于更新数据库
>>> db.drop_all() >>> db.create_all()原有的数据都销毁数据库迁移
2.1 插入记录函数
>>> 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_susan = User(username='susan', role=user_role) >>> user_david = User(username='david', role=user_role)
模型的构造函数接受的参数是使用关键字参数指定的模型属性初始值。注意,role 属性也可以使用,虽然它不是真正的数据库列,但倒是一对多关系的高级表示。这些新建对象的 id 属性并无明确设定,由于主键是由 Flask-SQLAlchemy 管理的。如今这些对象只存在于 Python 中,还未写入数据库。所以id 还没有赋值spa
经过数据库会话管理对数据库所作的改动,在 Flask-SQLAlchemy 中,会话由 db.session 表示。准备把对象写入数据库以前,先要将其添加到会话中code
或者简写成:>>> 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])把对象写入数据库调用 commit() 方法提交会话
>>> db.session.commit()
2.1 修改记录
下面这个例子把 "Admin" 角色重命名为 "Administrator":
>>> admin_role.name = 'Administrator' >>> db.session.add(admin_role) >>> db.session.commit()
2.1 删除记录
数据库会话还有个 delete() 方法。下面这个例子把 "Moderator" 角色从数据库中删除
>>> db.session.delete(mod_role) >>> db.session.commit()
2.1 查询记录
Flask-SQLAlchemy 为每一个模型类都提供了 query 对象。最基本的模型查询是取回对应表中的全部记录:
使用过滤器能够配置 query 对象进行更精确的数据库查询。下面这个例子查找角色为 "User" 的全部用户:>>> Role.query.all() [<Role u'Administrator'>, <Role u'User'>] >>> User.query.all() [<User u'john'>, <User u'susan'>, <User u'david'>]
若要查看 SQLAlchemy 为查询生成的原生 SQL 查询语句,只需把 query 对象转换成字符串 :>>> User.query.filter_by(role=user_role).all() # user_role = Role(name='User'), role=user_role [<User u'susan'>, <User u'david'>]
若是你退出了 shell 会话,前面这些例子中建立的对象就不会以 Python 对象的形式存在,而是做为各自数据库表中的行。若是你打开了一个新的 shell 会话,就要从数据库中读取行, 再从新建立 Python 对象。下面这个例子发起了一个查询,加载名为 "User" 的用户角色:>>> str(User.query.filter_by(role=user_role)) 'SELECT users.id AS users_id, users.username AS users_username, users.role_id AS users_role_id FROM users WHERE :param_1 = users.role_id'
可在 query 对象上调用的经常使用过滤器
>>> user_role = Role.query.filter_by(name='User').first()
过滤器 | 说明 |
---|---|
filter() | 把过滤器添加到原查询上,返回一个新查询 |
filter_by() | 把等值过滤器添加到原查询上,返回一个新查询 |
limit() | 使用指定的值限制原查询返回的结果数量,返回一个新查询 |
offset() | 偏移原查询返回的结果,返回一个新查询 |
order_by() | 根据指定条件对原查询结果进行排序,返回一个新查询 |
group_by() | 根据指定条件对原查询结果进行分组,返回一个新查询 |
在查询上应用指定的过滤器后
,经过调用 all() 执行查询,以列表的形式返回结果。除了 all() 以外,还有其余方法能触发查询执行
。
经常使用查询执行函数
方法 | 说明 |
---|---|
all() | 以列表形式返回查询的全部结果 |
first() | 返回查询的第一个结果,若是没有结果,则返回 None |
first_or_404() | 返回查询的第一个结果,若是没有结果,则终止请求,返回 404 错误响应 |
get() | 返回指定主键对应的行,若是没有对应的行,则返回 None |
get_or_404() | 返回指定主键对应的行,若是没找到指定的主键,则终止请求,返回 404 错误响应 |
count() | 返回查询结果的数量 |
paginate() | 返回一个 Paginate 对象,它包含指定范围内的结果 |
下面这个例子分别从关系的两端查询角色和用户之间的一对 多关系:
>>> 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'参数,从而禁止自动执行查询。
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