Flask 操作Mysql数据库 - flask-sqlalchemy扩展
数据库的设置
Web应用中普遍使用的是关系模型的数据库,关系型数据库把所有的数据都存储在表中,表用来给应用的实体建模,表的列数是固定的,行数是可变的。它使用结构化的查询语言。关系型数据库的列定义了表中表示的实体的数据属性。比如:商品表里有name、price、number等。 Flask本身不限定数据库的选择,你可以选择SQL或NOSQL的任何一种。也可以选择更方便的SQLALchemy,类似于Django的ORM。SQLALchemy实际上是对数据库的抽象,让开发者不用直接和SQL语句打交道,而是通过Python对象来操作数据库,在舍弃一些性能开销的同时,换来的是开发效率的较大提升。
SQLAlchemy是一个关系型数据库框架,它提供了高层的ORM和底层的原生数据库的操作。flask-sqlalchemy是一个简化了SQLAlchemy操作的flask扩展。
下面使用mysql作为示例进行说明。
创建mysql数据库
1.登录数据库
mysql -u root -p password
2.创建数据库,并设定编码
create database <数据库名> charset=utf8;
3.显示所有数据库
show databases;
4.执行
create database flask_test charset=utf8;
安装flask-sqlalchemy的扩展
pip install -U Flask-SQLAlchemy
python2:要连接mysql数据库,仍需要安装flask-mysqldb
pip install flask-mysqldb
python3:要连接mysql数据库,仍需要安装pymysql
pip install pymysql
本篇章内容以python3作为开讲。
使用Flask-SQLAlchemy连接mysql数据库
使用Flask-SQLAlchemy扩展操作数据库,首先需要建立数据库连接。数据库连接通过URL指定,而且程序使用的数据库必须保存到Flask配置对象的SQLALCHEMY_DATABASE_URI键中。
对比下Django和Flask中的数据库设置:
Django的数据库设置:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql', # 修改后端数据库使用mysql
'NAME': 'mydb', # 设置访问数据库名称
'USER': 'root', # 访问访问mysql用户名
'PASSWORD': 'password', # 设置访问密码
'HOST': 'localhost', # 设置访问ip地址
'PORT': 3306, # 设置访问端口号
}
}
Flask的数据库设置:
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://user:password@127.0.0.1:3306/database'
常用的SQLAlchemy字段类型
上面看完了如何设置连接数据库,那么来看看,使用SQLAlchemy创建数据模型的时候,基本的字段类型如下:
类型名 | 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 | 二进制文件 |
常用的SQLAlchemy列选项
选项名 | 说明 |
---|---|
primary_key | 如果为True,代表表的主键 |
unique | 如果为True,代表这列不允许出现重复的值 |
index | 如果为True,为这列创建索引,提高查询效率 |
nullable | 如果为True,允许有空值,如果为False,不允许有空值 |
default | 为这列定义默认值 |
常用的SQLAlchemy关系选项
选项名 | 说明 |
---|---|
backref | 在关系的另一模型中添加反向引用 |
primary join | 明确指定两个模型之间使用的联结条件 |
uselist | 如果为False,不使用列表,而使用标量值 |
order_by | 指定关系中记录的排序方式 |
secondary | 指定多对多中记录的排序方式 |
secondary join | 在SQLAlchemy中无法自行决定时,指定多对多关系中的二级联结条件 |
上面这些有很多基本选项的说明,下面来进行数据库的基本增删改等操作来加强理解。
数据库基本操作
在Flask-SQLAlchemy中,插入、修改、删除操作,均由数据库会话管理。会话用db.session表示。在准备把数据写入数据库前,要先将数据添加到会话中然后调用commit()方法提交会话。
数据库会话是为了保证数据的一致性,避免因部分更新导致数据不一致。提交操作把会话对象全部写入数据库,如果写入过程发生错误,整个会话都会失效。
数据库会话也可以回滚,通过db.session.rollback()方法,实现会话提交数据前的状态。
在Flask-SQLAlchemy中,查询操作是通过query对象操作数据。最基本的查询是返回表中所有数据,可以通过过滤器进行更精确的数据库查询。
下面先来创建两个表的数据模型:用户表和角色表。
在视图函数中定义模型类
看完了上面那么多的概念说明,下面来看看如何创建数据模型以及创建数据表,如下:
1.在脚本15_SQLAlchemy.py编写创建User和Role数据模型
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
import pymysql
pymysql.install_as_MySQLdb() app = Flask(__name__) class Config(object):
"""配置参数"""
# 设置连接数据库的URL
user = 'root'
password = '********'
database = 'flask_test'
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://%s:%s@127.0.0.1:3306/%s' % (user,password,database) # 设置sqlalchemy自动更跟踪数据库
SQLALCHEMY_TRACK_MODIFICATIONS = True # 查询时会显示原始SQL语句
app.config['SQLALCHEMY_ECHO'] = True # 禁止自动提交数据处理
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = False # 读取配置
app.config.from_object(Config) # 创建数据库sqlalchemy工具对象
db = SQLAlchemy(app) class Role(db.Model):
# 定义表名
__tablename__ = 'roles'
# 定义字段
id = db.Column(db.Integer, primary_key=True,autoincrement=True)
name = db.Column(db.String(64), unique=True)
users = db.relationship('User',backref='role') # 反推与role关联的多个User模型对象 class User(db.Model):
# 定义表名
__tablename__ = 'users'
# 定义字段
id = db.Column(db.Integer, primary_key=True,autoincrement=True)
name = db.Column(db.String(64), unique=True, index=True)
email = db.Column(db.String(64),unique=True)
pswd = db.Column(db.String(64))
role_id = db.Column(db.Integer, db.ForeignKey('roles.id')) # 设置外键 if __name__ == '__main__': # 删除所有表
db.drop_all() # 创建所有表
db.create_all()
- 执行脚本,创建数据库
python3 15_SQLAlchemy.py
3.在mysql查看已经创建的表结构
+--------------------+
| Tables_in_flask_ex |
+--------------------+
| roles |
| users |
+--------------------+
2 rows in set (0.00 sec) mysql>
mysql> desc users;
+---------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(64) | YES | UNI | NULL | |
| email | varchar(64) | YES | UNI | NULL | |
| pswd | varchar(64) | YES | | NULL | |
| role_id | int(11) | YES | MUL | NULL | |
+---------+-------------+------+-----+---------+----------------+
5 rows in set (0.00 sec) mysql>
mysql> desc roles;
+-------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(64) | YES | UNI | NULL | |
+-------+-------------+------+-----+---------+----------------+
2 rows in set (0.00 sec) mysql>
创建好了数据表之后,下面来看看如何执行数据的增删查改的。
常用的SQLAlchemy查询过滤器
过滤器 | 说明 |
---|---|
filter() | 把过滤器添加到原查询上,返回一个新查询 |
filter_by() | 把等值过滤器添加到原查询上,返回一个新查询 |
limit | 使用指定的值限定原查询返回的结果 |
offset() | 偏移原查询返回的结果,返回一个新查询 |
order_by() | 根据指定条件对原查询结果进行排序,返回一个新查询 |
group_by() | 根据指定条件对原查询结果进行分组,返回一个新查询 |
常用的SQLAlchemy查询执行器
方法 | 说明 |
---|---|
all() | 以列表形式返回查询的所有结果 |
first() | 返回查询的第一个结果,如果未查到,返回None |
first_or_404() | 返回查询的第一个结果,如果未查到,返回404 |
get() | 返回指定主键对应的行,如不存在,返回None |
get_or_404() | 返回指定主键对应的行,如不存在,返回404 |
count() | 返回查询结果的数量 |
paginate() | 返回一个Paginate对象,它包含指定范围内的结果 |
创建表:
db.create_all()
删除表
db.drop_all()
每次插入单条数据
if __name__ == '__main__': # 插入一条角色数据
role1 = Role(name='admin')
db.session.add(role1)
db.session.commit() # 再次插入一条数据
role2 = Role(name='user')
db.session.add(role2)
db.session.commit()
执行脚本:
python3 15_SQLAlchemy.py
在mysql中查看插入的数据,如下:
mysql> select * from roles \G
*************************** 1. row ***************************
id: 1
name: admin
*************************** 2. row ***************************
id: 2
name: user
2 rows in set (0.00 sec)
一次插入多条数据
# 一次性插入多条数据
user1 = User(name='wang',email='wang@163.com',pswd='123456',role_id=role1.id)
user2 = User(name='zhang',email='zhang@189.com',pswd='201512',role_id=role2.id)
user3 = User(name='chen',email='chen@126.com',pswd='987654',role_id=role2.id)
user4 = User(name='zhou',email='zhou@163.com',pswd='456789',role_id=role1.id)
db.session.add_all([user1,user2,user3,user4])
db.session.commit()
执行插入数据,如下:
python3 15_SQLAlchemy.py
在mysql中查询插入的数据如下:
mysql> select * from users \G
*************************** 1. row ***************************
id: 1
name: wang
email: wang@163.com
pswd: 123456
role_id: 1
*************************** 2. row ***************************
id: 2
name: zhang
email: zhang@189.com
pswd: 201512
role_id: 2
*************************** 3. row ***************************
id: 3
name: chen
email: chen@126.com
pswd: 987654
role_id: 2
*************************** 4. row ***************************
id: 4
name: zhou
email: zhou@163.com
pswd: 456789
role_id: 1
4 rows in set (0.00 sec) mysql>
虽然这里在python中看上去是一次性插入多条数据,其实在mysql也是执行多行插入的语句,通过mysql的日志可以看到如下:
2019-11-23T16:48:56.984459Z 9061 Query INSERT INTO users (name, email, pswd, role_id) VALUES ('wang', 'wang@163.com', '123456', 1)
2019-11-23T16:48:56.997132Z 9061 Query INSERT INTO users (name, email, pswd, role_id) VALUES ('zhang', 'zhang@189.com', '201512', 2)
2019-11-23T16:48:57.010175Z 9061 Query INSERT INTO users (name, email, pswd, role_id) VALUES ('chen', 'chen@126.com', '987654', 2)
2019-11-23T16:48:57.024134Z 9061 Query INSERT INTO users (name, email, pswd, role_id) VALUES ('zhou', 'zhou@163.com', '456789', 1)
实际上并没有将多个values合并到一个insert语句,依然是多个insert语句逐个插入的。
查询:filter_by精确查询
返回名字等于'wang'的所有user
User.query.filter_by(name='wang').all()
first()返回查询到的第一个对象
User.query.first()
all()返回查询到的所有对象
User.query.all()
filter模糊查询,返回名字结尾字符为g的所有数据。
User.query.filter(User.name.endswith('g')).all()
get(),参数为主键,如果主键不存在没有返回内容
User.query.get(1)
逻辑非,返回名字不等于wang的所有数据。
User.query.filter(User.name!='wang').all()
逻辑与,需要导入and_,返回and_()条件满足的所有数据。
from sqlalchemy import and_
User.query.filter(and_(User.name!='wang',User.email.endswith('163.com'))).all()
逻辑或,需要导入or_
from sqlalchemy import or_
User.query.filter(or_(User.name!='wang',User.email.endswith('163.com'))).all()
not_ 相当于取反
from sqlalchemy import not_
User.query.filter(not_(User.name=='chen')).all()
查询数据后删除
user = User.query.first()
db.session.delete(user)
db.session.commit()
User.query.all()
更新数据
user = User.query.first()
user.name = 'dong'
db.session.commit()
User.query.first()
使用update
User.query.filter_by(name='zhang').update({'name':'li'})
关联查询示例:角色和用户的关系是一对多的关系,一个角色可以有多个用户,一个用户只能属于一个角色。
关联查询角色的所有用户:
#查询roles表id为1的角色
role1 = Role.query.get(1)
#查询该角色的所有用户
role1.users
关联查询用户所属角色:
#查询users表id为3的用户
user1 = User.query.get(3)
#查询用户属于什么角色
user1.role
Flask 操作Mysql数据库 - flask-sqlalchemy扩展的更多相关文章
- Python 操作mysql数据库之 SQLAlchemy 案例详解
前言: 字段声明类型中,最右边的是数据库中对应的字段,我们依然可以使用,其左边的的 SQLAchemy 则是其自身封装的自定义类型. 本篇不会讲太多的理论知识,因为这个实用性更强,所以通篇全部都是 ...
- flask 操作mysql的两种方式-sqlalchemy操作
flask 操作mysql的两种方式-sqlalchemy操作 二.ORM sqlalchemy操作 #coding=utf-8 # model.py from app import db class ...
- php笔记08:数据库编程---使用php的MySQL扩展库操作MySQL数据库
1.使用php的MySQL扩展库操作MySQL数据库: php有3种方式操作MySQL数据库 (1)mysql扩展库 (2)mysqli扩展库 (3)pdo mysql扩展库与mysql数据库 ...
- mysqli扩展库操作mysql数据库
配置环境 配置php.ini文件让php支持mysqli扩展库 extension=php_mysqli.dll 建库建表 详见博客 “mysql扩展库操作mysql数据库” 查询数据库 <?p ...
- python【第十二篇下】操作MySQL数据库以及ORM之 sqlalchemy
内容一览: 1.Python操作MySQL数据库 2.ORM sqlalchemy学习 1.Python操作MySQL数据库 2. ORM sqlachemy 2.1 ORM简介 对象关系映射(英语: ...
- flask 操作mysql的两种方式-sql操作
flask 操作mysql的两种方式-sql操作 一.用常规的sql语句操作 # coding=utf-8 # model.py import MySQLdb def get_conn(): conn ...
- 使用php的mysqli扩展库操作mysql数据库
简单介绍mysqli: 1.mysqli(mysql improve mysql扩展库的增强版) mysql扩展库和mysqli扩展库的区别 1.mysqli的稳定性 安全性 和 执行效率有所提高 ...
- PHP mysql 扩展库 操作mysql数据库步骤
一.mysql 扩展库操作mysql数据库步骤如下: 1.获取连接 2.选择数据库 3.设置操作编码 4.发送指令(ddl数据定义/dml数据操作/dql数据查询/dtl数据事务控制) 5.接收返回的 ...
- 【tips】ORM - SQLAlchemy操作MySQL数据库
优先(官方文档SQLAlchemy-version1.2): sqlalchemy | 作者:斯芬克斯 推荐一(长篇幅version1.2.0b3):python约会之ORM-sqlalchemy | ...
随机推荐
- 第15.41节、PyQt(Python+Qt)入门学习:输入部件QComboBox组合框功能详解
专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 一.概述 Designer中输入工具部件中的Combo Box组合框与 ...
- CF1400G - Mercenaries
1400G - Mercenaries 考场上想到枚举,但是只想到了 \(2 ^ m\) 枚举矛盾,然后用 NOI Online 2 游戏 类似的容斥掉,结果式子推着推着就复杂度爆了 wtcl. (U ...
- AcWing 316 .减操作
题目链接 大型补档计划 没想出来去看题解了... 关键是发现无论怎样括号嵌套,每个元素始终只有对答案的贡献为 + a[i] 或者 - a[i]. 而且第一个必然贡献是 +1, 第二个必然是 -1. 所 ...
- uni-app中使用sass
uni-app在创建时,工程目录下会有个uni.scss文件,我们可以直接在里面定制化scss变量. 全局scss中的坑: 1.如果要引用全局外部scss文件,可以考虑在uni.scss这个系统全局s ...
- SpringBoot + SpringSecurity + Mybatis-Plus + JWT + Redis 实现分布式系统认证和授权(刷新Token和Token黑名单)
1. 前提 本文在基于SpringBoot整合SpringSecurity实现JWT的前提中添加刷新Token以及添加Token黑名单.在浏览之前,请查看博客: SpringBoot + Sp ...
- Jmeter二次开发——基于Java请求
简述 这近几年,越来越多非http的协议需要进行性能测试,包括不仅限于各类rpc.mq.缓存等.对于这些协议,市面上可能没有现成的工具可以直接使用,这个时候,我们可以自己动手,通过编写相应的JavaS ...
- 用DirectX12实现Blinn Phong
这次我们来用DirectX12实现一下基本的Blinn Phong光照模型.让我们再把这个光照模型的概念过一遍:一个物体的颜色由三个因素决定:ambient, diffuse, specular.am ...
- 如何正确运用break、continue和return
break.continue和return 一.break 作用:跳出(离break语句最近的)循环 栗子: for(int i = 1;i <= 100;i++){ System.out.pr ...
- gcc编译阶段打印宏定义的内容
背景 总所周知,代码量稍微大一点的C/C++项目的一些宏定义都会比较复杂,有时候会嵌套多个#if/#else判断分支和一堆#ifdef/#undef让你单看代码的话很难判断出宏定义的具体内容. 如果有 ...
- 工作流学习之 IDEA 使用activiti插件 出现乱码
今天学习 工作流 (work flow ) 的时候遇到了一点小问题 就是在 activitit的插件的时候 出现了乱码,弄了很久,终于解决了,就做个总结 嘻嘻 当场懵了,我记得我改了编码呀 - (Se ...