定义
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db'
db = SQLAlchemy(app)
or
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
db = SQLAlchemy()
db.init_app(app)
config[config_name].init_app(app) # config.py里,指定了数据库文件,比如 mysql:///, sqlite:///
关系
一对多(one-to-many)
关系使用relationship()
函数表示。然而外键必须用类sqlalchemy.schema.ForeignKey
单独声明:
class Person(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50))
addresses = db.relationship('Address', backref='person',
lazy='dynamic')
class Address(db.Model):
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(50))
person_id = db.Column(db.Integer, db.ForeignKey('person.id'))
一对一
只需要添加uselist=False
属性
class Person(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50))
addresses = db.relationship('Address', backref='person',
lazy='dynamic', uselist=False)
class Address(db.Model):
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(50))
person_id = db.Column(db.Integer, db.ForeignKey('person.id'))
多对多关系(many-to-many)
如果您想要用多对多关系,您需要定义一个用于关系的辅助表。对于这个辅助表, 强烈建议不使用模型,而是采用一个实际的表:
tags = db.Table('tags',
db.Column('tag_id', db.Integer, db.ForeignKey('tag.id')),
db.Column('page_id', db.Integer, db.ForeignKey('page.id'))
)
class Page(db.Model):
id = db.Column(db.Integer, primary_key=True)
tags = db.relationship('Tag', secondary=tags,
backref=db.backref('pages', lazy='dynamic'))
class Tag(db.Model):
id = db.Column(db.Integer, primary_key=True)
多对多关系使用(在使用多对多关系时需要先将相对应的对象查询出来):
- 添加关系
page_1 = Page()
tag_1 = Tag()
db.session.add(page_1)
db.session.add(tag_1)
db.session.commit()
# 添加对应关系
page_1.tags.append(tag_1)
db.session.add(page_1)
db.session.commit()
- 删除关系
page_1.tags.remove(tag_1)
db.session.add(page_1)
db.session.commit()
- 查询
# 列出所有的tags数组
page_1.tags.all()
操作
models.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', lazy="dynamic")
def __init__(self, name):
self.name = name
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)
role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))
def __init__(self, username, role):
self.username = username
self.role = role
def __repr__(self):
return '<User %r>' % self.username
创建 删除表
db.create_all()
db.drop_all()
插入行
admin_role = Role(name='Admin')
db.session.add(admin_role)
db.session.commit()
修改行
admin_role.name = 'Administartor'
db.session.add(admin_role)
db.session.commit()
删除行
db.session.delete(admin_role)
db.session.commit()
查询行
Flask-SQLAlchemy为每个模型类都提供了query
对象。
Role.query.all()
User.query.filter_by(role=user_role).all()
常用的SQLAlchemy查询过滤器
方法 | 说明 |
---|---|
filter() | 把过滤器添加到原查询上,返回一个新查询 |
filter_by() | 把等值过滤器添加到原查询上,返回一个新查询 |
limit() | 使用指定的值限制原查询返回的结果数量,返回一个新查询 |
offset() | 偏移原查询返回的结果,返回一个新查询 |
order_by() | 根据指定条件对原查询结果进行排序,返回一个新查询 |
group_by() | 根据指定条件对原查询结果进行分组,返回一个新查询 |
方法 | 说明 |
---|---|
all() | 以列表形式返回查询的所有结果 |
first() | 返回查询的第一个结果,如果没有结果,则返回 None |
first_or_404() | 返回查询的第一个结果,如果没有结果,则终止请求,返回 404 错误响应 |
get() | 返回指定主键对应的行,如果没有对应的行,则返回 None |
get_or_404() | 返回指定主键对应的行,如果没找到指定的主键,则终止请求,返回 404 错误响应 |
count() | 返回查询结果的数量 |
paginate() | 返回一个 Paginate 对象,它包含指定范围内的结果 |
常用的SQLAlchemy查询执行函数
方法 | 说明 |
---|---|
all() | 以列表形式返回查询的所有结果 |
first() | 返回查询的第一个结果,如果没有结果,则返回 None |
first_or_404() | 返回查询的第一个结果,如果没有结果,则终止请求,返回 404 错误响应 |
get() | 返回指定主键对应的行,如果没有对应的行,则返回 None |
get_or_404() | 返回指定主键对应的行,如果没找到指定的主键,则终止请求,返回 404 错误响应 |
count() | 返回查询结果的数量 |
paginate() | 返回一个 Paginate 对象,它包含指定范围内的结果 |
Flask 数据库迁移工具 flask-migrate
仅当数据库表不存在时,Flask-SQLAlchemy 才会根据模型进行创建。因此,更新表的唯一方式就是先删除旧表,不过这样做会丢失数据库中的所有数据
manage.py
添加db命令
from flask_migrate import Migrate, MigrateCommand
migrate = Migrate(app, db)
manager.add_command("db", MigrateCommand)
第一次使用:
- 初始化:
python manage.py db init
这个命令会在项目下创建 migrations 文件夹,所有迁移脚本都存放其中。 - 创建第一个版本:
python manage.py db migrate -m "initial migration"
检查migrations/versions,检查里面表格及字段 - 运行升级
python manage.py db upgrade
,会把项目使用的数据库文件,更新为新的表格、字段,同时保留数据
更新:
- 更新表格的字段
- 再次运行一下
db migrate -m 'xx'
-> 相当于commit 更新到/migrate目录 -
db upgrade
-> 数据库会更新