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 数据库的有关操作就到此结束了,有什么问题可以给我留言,看到会回复大家的

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

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. 并发问题引出ThreadLocal

    ThreadLocal Thread-->人类Runnable-->任务类 多线程并发问题引出ThreadLocal 多线程并发问题的原因: 操作同一个对象,对对象具有读写权限(只读如拍照 ...

  2. 关于CString与VARIANT(CComVariant)之间的转化

    一.VARIANT.CComVariant类与CString是什么: CString是MFC定义的字符串类,VARIANT是COM标准为了使COM组件能够被各种语言使用(vc++.vb.java.py ...

  3. PS 滤镜— —Marble 效果

    clc; clear all; close all; addpath('E:\PhotoShop Algortihm\Image Processing\PS Algorithm'); I=imread ...

  4. UVA12163 游戏

    题目大意 现在有两个人在一个n个结点的有向图上玩一个双人游戏,保证图中无环和自圈.游戏的规则如下:1.初始的时候$i$号点有一个正权值$value_i$2.两名玩家依次操作,每个玩家在当前回合可以选择 ...

  5. 搞事情 -- python之线程

    简介 操作系统线程理论 线程概念的引入背景 线程的特点 进程和线程的关系 使用线程的实际场景 用户级线程和内核级线程(了解) 线程和python 理论知识 线程的创建Threading.Thread类 ...

  6. LOJ2305 「NOI2017」游戏

    「NOI2017」游戏 题目背景 狂野飙车是小 L 最喜欢的游戏.与其他业余玩家不同的是,小 L 在玩游戏之余,还精于研究游戏的设计,因此他有着与众不同的游戏策略. 题目描述 小 L 计划进行$n$场 ...

  7. 【LeetCode】012. Integer to Roman

    Given an integer, convert it to a roman numeral. Input is guaranteed to be within the range from 1 t ...

  8. 迁移学习-微调(fine-tune)的注意事项:

    选取微调形式的两个重要因素:新数据集的大小(size)和相似性(与预训练的数据集相比).牢记卷积网络在提取特征时,前面的层所提取的更具一般性,后面的层更加具体,更倾向于原始的数据集(more orig ...

  9. css--offsetParent

    offsetParent属性返回一个对象的引用,这个对象是距离调用offsetParent的元素最近的(在包含层次中最靠近的),并且是已进行过CSS定位的容器元素. 如果这个容器元素未进行CSS定位, ...

  10. django基础PROJECT APP View template

    project 和 app 的区别就是一个是配置另一个是代码: 一个project包含很多个Django app以及对它们的配置. 一个project的作用是提供配置文件,比方说哪里定义数据库连接信息 ...