Flask ORM

在Django框架中内部已经提供ORM这样的框架,来实现对象关系映射,方便我们操作数据库。如果想在Flask中也达到这样效果,需要安装一个第三方来支持。

SQLAlchemy是一个关系型数据库框架,它提供了高层的ORM和底层的原生数据库的操作。flask-sqlalchemy是一个简化了SQLAlchemy操作的flask扩展。

安装

pip install flask-sqlalchemy

这里以mysql数据库为例

安装pymysql

pip install pymysql

相关配置

  1. from flask import Flask
  2. from flask_sqlalchemy import SQLAlchemy
  3. import pymysql
  4. pymysql.install_as_MySQLdb()
  5. app = Flask(__name__)
  6. # 设置连接数据库的URL
  7. app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:123456@127.0.0.1:3306/db_flask'
  8. # 数据库和模型类同步修改
  9. app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
  10. # 查询时会显示原始SQL语句
  11. app.config['SQLALCHEMY_ECHO'] = True
  12. # 管理app
  13. 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(),实现回话提交数据到以前的状态

模型类
  1. """
  2. 相关配置的代码 记得改为你自己的数据库
  3. """
  4. class Type(db.Model):
  5. __tablename__ = 'tbl_type' # 表的名字 如果不写就以类名命名
  6. id = db.Column(db.Integer,primary_key=True) # 主建
  7. name = db.Column(db.String)
  8. id = db.Column(db.Integer, primary_key=True) # 主键
  9. name = db.Column(db.String(32), unique=True) # 名字
  10. # 数据库中不存在的字段,只是为了查找和反向查找。
  11. # backref:在关系的另一模型中添加反向引用
  12. heros = db.relationship("Hero", backref='type')
  13. # 英雄
  14. class Hero(db.Model):
  15. # 表名
  16. __tablename__ = 'tbl_heros'
  17. # 数据库真正存在的字段
  18. id = db.Column(db.Integer, primary_key=True) # 主键
  19. name = db.Column(db.String(64), unique=True) # 名字
  20. gender = db.Column(db.String(64)) # 性别
  21. # 外键 一个射手对应很多英雄
  22. type_id = db.Column(db.Integer, db.ForeignKey("tbl_types.id"))
  23. if __name__ == "__main__":
  24. db.create_all() # 创建表
  25. type1 = Type(name='射手')
  26. db.session.add(type1) # 添加到会话
  27. db.session.commit() # 提交
  28. type2 = Type(name='坦克')
  29. db.session.add(type2)
  30. db.session.commit()
  31. type3 = Type(name='法师')
  32. type4 = Type(name='刺客')
  33. db.session.add_all([type3, type4]) # 添加多个
  34. db.session.commit()
  35. hero1 = Hero(name='后羿', gender='男', type_id=type1.id)
  36. hero2 = Hero(name='程咬金', gender='男', type_id=type2.id)
  37. hero3 = Hero(name='王昭君', gender='女', type_id=type3.id)
  38. hero4 = Hero(name='安琪拉', gender='女', type_id=type3.id)
  39. hero5 = Hero(name='兰陵王', gender='男', type_id=type4.id)
  40. db.session.add_all([hero1, hero2, hero3, hero4, hero5]) # 添加多个
  41. 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

使用
  1. from flask import Flask
  2. from flask_sqlalchemy import SQLAlchemy
  3. import pymysql
  4. from flask_migrate import Migrate, MigrateCommand
  5. from flask_script import Manager
  6. pymysql.install_as_MySQLdb()
  7. app = Flask(__name__)
  8. # 通过脚本管理flask程序
  9. manager = Manager(app)
  10. """
  11. 相关配置
  12. """
  13. db = SQLAlchemy(app)
  14. # 创建数据库迁移对象
  15. Migrate(app, db)
  16. # 向脚步管理添加数据库迁移命令 db指命令的别名
  17. manager.add_command('db', MigrateCommand)
  18. """
  19. 模型代码
  20. """

初始化 只是在每个项目第一次生成迁移用到 以后就不用了

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 >>版本号

模型关系

在数据库中,我们知道数据关系大概有如下几种:一对一、一对多、多对多、自关联等。我们模型已经描述过了一对多,那么下面我们在用模型把其它关系也写出来。

一对一

  1. # 文章模型
  2. class Article(db.Model):
  3. # 表名
  4. __tablename__ = 'tbl_article'
  5. # 数据库真正存在的字段
  6. id = db.Column(db.Integer, primary_key=True) # 主键
  7. title = db.Column(db.String(128), unique=True) # 名字
  8. # 方便查找,数据并不存在的字段
  9. content = db.relationship('Acontent', backref='article', uselist=False) #一对一需要把uselist设置为False
  10. # 内容模型
  11. class Acontent(db.Model):
  12. # 表名
  13. __tablename__ = 'tbl_acontent'
  14. # 数据库真正存在的字段
  15. id = db.Column(db.Integer, primary_key=True) # 主键
  16. content = db.Column(db.Text(4000)) # 名字
一对多
  1. # 分类模型
  2. class Category(db.Model):
  3. # 表名
  4. __tablename__ = 'tbl_category'
  5. # 数据库真正存在的字段
  6. id = db.Column(db.Integer, primary_key=True) # 主键
  7. name = db.Column(db.String(32), unique=True) # 名字
  8. # 方便查找,数据并不存在的字段
  9. article = db.relationship('Article', backref='category')
  10. # 文章模型
  11. class Article(db.Model):
  12. # 表名
  13. __tablename__ = 'tbl_article'
  14. # 数据库真正存在的字段
  15. id = db.Column(db.Integer, primary_key=True) # 主键
  16. title = db.Column(db.String(128), unique=True) # 名字
  17. category_id = db.Column(db.Integer, db.ForeignKey('tbl_category.id')) # 分类id
多对多
  1. # 辅助表
  2. tbl_tags = db.Table('tbl_tags',
  3. db.Column('tag_id', db.Integer, db.ForeignKey('tbl_tag.id')),
  4. db.Column('article_id', db.Integer, db.ForeignKey('tbl_article.id'))
  5. )
  6. # 标签模型
  7. class Tag(db.Model):
  8. # 表名
  9. __tablename__ = 'tbl_tag'
  10. # 数据库真正存在的字段
  11. id = db.Column(db.Integer, primary_key=True) # 主键
  12. name = db.Column(db.String(32), unique=True) # 名字
  13. # 文章模型
  14. class Article(db.Model):
  15. # 表名
  16. __tablename__ = 'tbl_article'
  17. # 数据库真正存在的字段
  18. id = db.Column(db.Integer, primary_key=True) # 主键
  19. title = db.Column(db.String(128), unique=True) # 名字
  20. category_id = db.Column(db.Integer, db.ForeignKey('tbl_category.id')) # 分类id
  21. # 方便查找,数据并不存在的字段
  22. content = db.relationship('Acontent', backref='article')
  23. tags = db.relationship('Tag', secondary=tbl_tags, backref='articles')
  24. # secondary=tbl_tags, tbl_tags->辅助表的名字 注意!!!
自关联
  1. # 地区模型
  2. class Area(db.Model):
  3. # 表名
  4. __tablename__ = "tbl_area"
  5. # 数据库真正存在的字段
  6. id = db.Column(db.Integer, primary_key=True) # 主键
  7. name = db.Column(db.Text, nullable=False) # 地区名字
  8. parent_id = db.Column(db.Integer, db.ForeignKey("tbl_area.id")) # 父评论id
  9. # 方便查找,数据并不存在的字段
  10. parent = db.relationship("Area", remote_side=[id]) # 自关联需要加remote_side

flask 数据库的有关操作就到此结束了,有什么问题可以给我留言,看到会回复大家的

喜欢就点播关注吧-_-!

flask数据操纵的更多相关文章

  1. flask+sqlite3+echarts2+ajax数据可视化

    前提: 准备Python + Flask+Sqlite3的平台环境(windows系统) 前面一节介绍flask怎么安装了,剩下sqlite3下载后解压,然后环境变量添加解压路径就行了 附加下载地址: ...

  2. flask+sqlite3+echarts2+ajax数据可视化报错:UnicodeDecodeError: 'utf8' codec can't decode byte解决方法

    flask+sqlite3+echarts2+ajax数据可视化报错: UnicodeDecodeError: 'utf8' codec can't decode byte 解决方法: 将 py文件和 ...

  3. Windows下快速安装Flask的一次经历

    前提: 1.已安装python版本(一般都是2.X) 2.已安装easy_install python安装,记得配置Python的环境变量,例如:我的直接在Path上加 G:\Python 验证安装P ...

  4. 使用Flask设计带认证token的RESTful API接口[翻译]

    上一篇文章, 使用python的Flask实现一个RESTful API服务器端  简单地演示了Flask实的现的api服务器,里面提到了因为无状态的原则,没有session cookies,如果访问 ...

  5. 使用python的Flask实现一个RESTful API服务器端[翻译]

    最近这些年,REST已经成为web services和APIs的标准架构,很多APP的架构基本上是使用RESTful的形式了. 本文将会使用python的Flask框架轻松实现一个RESTful的服务 ...

  6. python flask (一)

    from flask import Flask app = Flask(__name__) @app.route('/') def hello_world(): return 'Hello World ...

  7. flask源码分析

    本flask源码分析不间断更新 而且我分析的源码全是我个人觉得是很beautiful的 1 flask-login 1.1 flask.ext.login.login_required(func),下 ...

  8. Python flask 基于 Flask 提供 RESTful Web 服务

    转载自 http://python.jobbole.com/87118/ 什么是 REST REST 全称是 Representational State Transfer,翻译成中文是『表现层状态转 ...

  9. Python flask @app.route

    转载自 http://python.jobbole.com/80956/ 下面是Flask主页给我们的第一个例子,我们现在就由它入手,深入理解“@app.route()”是如何工作的.         ...

随机推荐

  1. C/C++ 安全编码 —— 不安全的函数

    1. 文件与IO操作 gets():从控制台输入到字符数组: char response[8]; gets(response); 如果控制台输入超过 8 个字符,程序便会发生不确定的行为.其主要问题在 ...

  2. 基于libRTMP的流媒体直播之 AAC、H264 推送

    这段时间在捣腾基于 RTMP 协议的流媒体直播框架,其间参考了众多博主的文章,剩下一些细节问题自行琢磨也算摸索出个门道,现将自己认为比较恼人的 AAC 音频帧的推送和解析.H264 码流的推送和解析以 ...

  3. C++ STL, set用法。 待更新zzzzz

    set集合容器:实现了红黑树的平衡二叉检索树的数据结构,插入元素时,它会自动调整二叉树的排列,把元素放到适当的位置,以保证每个子树根节点键值大于左子树所有节点的键值,小于右子树所有节点的键值:另外,还 ...

  4. Oracle RAC TAF 无缝failover

    理论背景: TAF( Transparent Application Failover ) allows oracle clients to reconnect to a surviving inst ...

  5. Springboot监控之一:SpringBoot四大神器之Actuator之2--spring boot健康检查对Redis的连接检查的调整

    因为项目里面用到了redis集群,但并不是用spring boot的配置方式,启动后项目健康检查老是检查redis的时候状态为down,导致注册到eureka后项目状态也是down.问下能不能设置sp ...

  6. css基础知识一

    1.CSS (Cascding Style Sheet)层叠样式表 级联样式表 样式表 2.CSS作用: 修改页面中元素的显示样式 能够实现内容与表现的分离 提高代码的可重用性和可维护性 3.导入CS ...

  7. Linux系统中‘dmesg’命令处理故障和收集系统信息的7种用法

    转自:https://linux.cn/article-3587-1.html 'dmesg'命令显示linux内核的环形缓冲区信息,我们可以从中获得诸如系统架构.cpu.挂载的硬件,RAM等多个运行 ...

  8. Ruby迭代器(Iterator)

    简单的讲,一个迭代器就是一个能接受代码块的方法.当初为了进行迭代操作而设置了带块方法,现在很多时候仍然称它为迭带器. 可实际上,早期版本的 Ruby 将使用代码块的方法称为迭代器,因为它们就是被设计来 ...

  9. SQL一对多特殊查询,取唯一一条

    主表: 辅表: 一个app对应多个apk,现在要取上线(Apk_Status最大的)的应用 select * from [dbo].[tbl_APP] as app join ( * from tbl ...

  10. 元素(Element)和结点(Node)的区别(org.w3c.dom)

    1.元素(Element)和结点(Node)的区别, 元素是一个小范围的定义,必须是含有完整信息的结点才是一个元素,例如 - . 但是一个结点不一定是一个元素,而一个元素一定是一个结点. 什么是nod ...