flask数据操纵
flask orm
在django框架中内部已经提供orm这样的框架,来实现对象关系映射,方便我们操作数据库。如果想在flask中也达到这样效果,需要安装一个第三方来支持。
sqlalchemy是一个关系型数据库框架,它提供了高层的orm和底层的原生数据库的操作。flask-sqlalchemy是一个简化了sqlalchemy操作的flask扩展。
安装
pip install flask-sqlalchemy
这里以mysql数据库为例
安装pymysql
pip install pymysql
相关配置
from flask import flask from flask_sqlalchemy import sqlalchemy import pymysql pymysql.install_as_mysqldb() app = flask(__name__) # 设置连接数据库的url app.config['sqlalchemy_database_uri'] = 'mysql://root:123456@127.0.0.1:3306/db_flask' # 数据库和模型类同步修改 app.config['sqlalchemy_track_modifications'] = true # 查询时会显示原始sql语句 app.config['sqlalchemy_echo'] = true # 管理app db = sqlalchemy(app)
字段类型
类型 | 对应python中 | 说明 |
---|---|---|
integer | int | 普通整数,一般是32位 |
smallinteger | int | 取值范围小的整数,一般是16位 |
biginteger | int或long | 不限制精度的整数 |
float | float | 浮点数 |
numeric | decimal.decimal | 普通整数,一般是32位 |
string | str | 变长字符串 |
text | str | 变长字符串,对较长或不限长度的字符串做了优化 |
unicode | unicode | 变长unicode字符串 |
unicodetext | unicode | 变长unicode字符串,对较长或不限长度的字符串做了优化 |
boolean | bool | 布尔值 |
date | datetime.date | 时间 |
time | datetime.datetime | 日期和时间 |
largebinary | str | 二进制文件 |
约束类型
选项 | 说明 | |
---|---|---|
primary_key | 如果为true,代表表的主键 | |
unique | 如果为true,代表这列不允许出现重复的值 | |
index | 如果为true,为这列创建索引,提高查询效率 | |
nullable | 如果为true,允许有空值,如果为false,不允许有空值 | |
default | 为这列定义默认值 |
关系类型
选项 | 说明 |
---|---|
backref | 在关系的另一模型中添加反向引用 |
primary join | 明确指定两个模型之间使用的联结条件 |
uselist | 如果为false,不使用列表,而使用标量值 |
order_by | 指定关系中记录的排序方式 |
secondary | 指定多对多中记录的排序方式 |
secondary join | 在sqlalchemy中无法自行决定时,指定多对多关系中的二级联结 |
创建
在flask-sqlalchemy中,插入、修改、删除操作,均由数据库会话管理。会话用db.session表示。在准备把数据写入数据库前,要先将数据添加到会话中然后调用commit()方法提交会话。
如果失败还可以回滚:db.rollback(),实现回话提交数据到以前的状态
模型类
""" 相关配置的代码 记得改为你自己的数据库 """ class type(db.model): __tablename__ = 'tbl_type' # 表的名字 如果不写就以类名命名 id = db.column(db.integer,primary_key=true) # 主建 name = db.column(db.string) id = db.column(db.integer, primary_key=true) # 主键 name = db.column(db.string(32), unique=true) # 名字 # 数据库中不存在的字段,只是为了查找和反向查找。 # backref:在关系的另一模型中添加反向引用 heros = db.relationship("hero", backref='type') # 英雄 class hero(db.model): # 表名 __tablename__ = 'tbl_heros' # 数据库真正存在的字段 id = db.column(db.integer, primary_key=true) # 主键 name = db.column(db.string(64), unique=true) # 名字 gender = db.column(db.string(64)) # 性别 # 外键 一个射手对应很多英雄 type_id = db.column(db.integer, db.foreignkey("tbl_types.id")) if __name__ == "__main__": db.create_all() # 创建表 type1 = type(name='射手') db.session.add(type1) # 添加到会话 db.session.commit() # 提交 type2 = type(name='坦克') db.session.add(type2) db.session.commit() type3 = type(name='法师') type4 = type(name='刺客') db.session.add_all([type3, type4]) # 添加多个 db.session.commit() hero1 = hero(name='后羿', gender='男', type_id=type1.id) hero2 = hero(name='程咬金', gender='男', type_id=type2.id) hero3 = hero(name='王昭君', gender='女', type_id=type3.id) hero4 = hero(name='安琪拉', gender='女', type_id=type3.id) hero5 = hero(name='兰陵王', gender='男', type_id=type4.id) db.session.add_all([hero1, hero2, hero3, hero4, hero5]) # 添加多个 db.session.commit()
到你数据库查一下
查询
flask-sqlalchemy中常用过滤器:
过滤器 | 说明 | |
---|---|---|
filter() | 把过滤器添加到原查询上,返回一个新查询 | |
filter_by() | 把等值过滤器添加到原查询上,返回一个新查询 | |
limit() | 使用指定的值限定原查询返回的结果 | |
offset() | 偏移原查询返回的结果,返回一个新查询 | |
order_by() | 根据指定条件对原查询结果进行排序,返回一个新查询 | |
group_by() | 根据指定条件对原查询结果进行分组,返回一个新查询 |
flask-sqlalchemy中常用执行器:
方法 | 说明 | |
---|---|---|
all() | 以列表形式返回查询的所有结果 | |
first() | 返回查询的第一个结果,如果未查到,返回none | |
first_or_404() | 返回查询的第一个结果,如果未查到,返回404 | |
get() | 返回指定主键对应的行,如不存在,返回none | |
get_or_404() | 返回指定主键对应的行,如不存在,返回404 | |
count() | 返回查询结果的数量 | |
paginate() | 返回一个paginate对象,它包含指定范围内的结果 |
这里举几个例子:
查全部分类:
type.query.all()
根据分类过滤:
type.query.filter_by(id = 1)
注意:
filter和 filter_by 的区别:
type.query.filter(类.字段 == 条件) type.query.filter_by(字段 = 条件)
逻辑与
hero.query.filter_by(name='王昭君',type_id=3).first()
逻辑或
from sqlalchemy import or_
hero.query.filter(or_(hero.name.endswith('君'),hero.type_id==3)).all()
排序
降序查询
hero.query.order_by(hero.id.desc()).all()
升序查询
hero.query.order_by(hero.id.asc()).all()
各种查询方法还有很多,大家可以去google或是百度
更新
- 第一种
hero = hero.query.get(1)
hero.name = '伽罗'
db.session.add(hero)
db.session.commit() - 第二种
hero.query.filter_by(id=1).update({"name":"虞姬","gender":"女"})
db.session.commit()
删除
hero = hero.query.get(4)
db.session.delete(hero)
db.session.commit()
模型迁移
在django框架开发过程中,我们对数据库字段添加或删除,直接修改模型类,然后进行迁移可以了,非常方便。我们也想让flask框架支持这样的操作,就需要使用flask-migrate扩展,来实现数据迁移。并且集成到flask-script中,所有操作通过命令就能完成。
安装插件
pip install flask-script
pip install flask-migrate
使用
from flask import flask from flask_sqlalchemy import sqlalchemy import pymysql from flask_migrate import migrate, migratecommand from flask_script import manager pymysql.install_as_mysqldb() app = flask(__name__) # 通过脚本管理flask程序 manager = manager(app) """ 相关配置 """ db = sqlalchemy(app) # 创建数据库迁移对象 migrate(app, db) # 向脚步管理添加数据库迁移命令 db指命令的别名 manager.add_command('db', migratecommand) """ 模型代码 """
初始化 只是在每个项目第一次生成迁移用到 以后就不用了
python3 app.py db init
app.py >> 你自己的文件名 db >> 上面指定的命令别名
在你的项目文件下 多出 migrations 的文件
生成迁移文件
python app.py db migrate -m 'first create'
提示:
info [alembic.runtime.migration] context impl mysqlimpl.
info [alembic.runtime.migration] will assume non-transactional ddl.
info [alembic.env] no changes in schema detected.
提交:
python flask_migrate_db.py db upgrade
ok 你的数据库已经有了数据
回退:
回退数据库时,需要指定回退版本号,由于版本号是随机字符串,为避免出错,建议先使用python flask_migrate_db.py db history命令查看历史版本的具体版本号,然后复制具体版本号执行回退。
python flask_migrate_db.py db downgrade base
python flask_migrate_db.py db downgrade 4cee71e47df3
4cee71e47df3 >>版本号
模型关系
在数据库中,我们知道数据关系大概有如下几种:一对一、一对多、多对多、自关联等。我们模型已经描述过了一对多,那么下面我们在用模型把其它关系也写出来。
一对一
# 文章模型 class article(db.model): # 表名 __tablename__ = 'tbl_article' # 数据库真正存在的字段 id = db.column(db.integer, primary_key=true) # 主键 title = db.column(db.string(128), unique=true) # 名字 # 方便查找,数据并不存在的字段 content = db.relationship('acontent', backref='article', uselist=false) #一对一需要把uselist设置为false # 内容模型 class acontent(db.model): # 表名 __tablename__ = 'tbl_acontent' # 数据库真正存在的字段 id = db.column(db.integer, primary_key=true) # 主键 content = db.column(db.text(4000)) # 名字
一对多
# 分类模型 class category(db.model): # 表名 __tablename__ = 'tbl_category' # 数据库真正存在的字段 id = db.column(db.integer, primary_key=true) # 主键 name = db.column(db.string(32), unique=true) # 名字 # 方便查找,数据并不存在的字段 article = db.relationship('article', backref='category') # 文章模型 class article(db.model): # 表名 __tablename__ = 'tbl_article' # 数据库真正存在的字段 id = db.column(db.integer, primary_key=true) # 主键 title = db.column(db.string(128), unique=true) # 名字 category_id = db.column(db.integer, db.foreignkey('tbl_category.id')) # 分类id
多对多
# 辅助表 tbl_tags = db.table('tbl_tags', db.column('tag_id', db.integer, db.foreignkey('tbl_tag.id')), db.column('article_id', db.integer, db.foreignkey('tbl_article.id')) ) # 标签模型 class tag(db.model): # 表名 __tablename__ = 'tbl_tag' # 数据库真正存在的字段 id = db.column(db.integer, primary_key=true) # 主键 name = db.column(db.string(32), unique=true) # 名字 # 文章模型 class article(db.model): # 表名 __tablename__ = 'tbl_article' # 数据库真正存在的字段 id = db.column(db.integer, primary_key=true) # 主键 title = db.column(db.string(128), unique=true) # 名字 category_id = db.column(db.integer, db.foreignkey('tbl_category.id')) # 分类id # 方便查找,数据并不存在的字段 content = db.relationship('acontent', backref='article') tags = db.relationship('tag', secondary=tbl_tags, backref='articles') # secondary=tbl_tags, tbl_tags->辅助表的名字 注意!!!
自关联
# 地区模型 class area(db.model): # 表名 __tablename__ = "tbl_area" # 数据库真正存在的字段 id = db.column(db.integer, primary_key=true) # 主键 name = db.column(db.text, nullable=false) # 地区名字 parent_id = db.column(db.integer, db.foreignkey("tbl_area.id")) # 父评论id # 方便查找,数据并不存在的字段 parent = db.relationship("area", remote_side=[id]) # 自关联需要加remote_side
flask 数据库的有关操作就到此结束了,有什么问题可以给我留言,看到会回复大家的
喜欢就点播关注吧-_-!
上一篇: python学习之数组二
下一篇: 手把手教你grid布局