Flask-SQLAlchemy相关与Flask-Migrate相关
SQL数据库
NoSQL数据库
使用Flask-SQLAlchemy管理数据库
MySQL
|
mysql://username:password@hostname/database
|
Postgres |
postgresql://username:password@hostname/database
|
SQLite(linux等)
|
sqlite:///absolute/path/to/database
|
SQLite(win)
|
sqlite:///c:/absolute/path/to/database
|
from flask_sqlalchemy import SQLAlchemy
from flask import Flask
app = Flask(__name__) app.config["SQLALCHEMY_DATABASE_URI"] = 'mysql://username:password@hostname/database' # 自动追踪,同步修改模型和数据库中的改动,建议设为False,降低内存消耗
app.config[SQLALCHEMY_TRACK_MODIFICATIONS] = False # db是SQLAlchemy类的实例,表示应用使用的数据库
db = SQLAlchemy(app)
定义模型
class Role(db.Model):
__tablename__ = "tbl_role"
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(32), unique=True)
users = db.relationship("User", backref="role") # 不是数据库中真实存在,建立两个表的关系,可通过role访问user,backref用于另一个表反推这个表 def __repr__(self):
"""定义后,可以让显示对象时更直观,自定义显示信息"""
return "Role object: name=%s" % self.name class User(db.Model):
"""用户表"""
__tablename__ = "tbl_users" # 指明数据库表名
id = db.Column(db.Integer, primary_key=True) # 指明表的主键,整型的主键会默认设置为自增主键
name = db.Column(db.String(64), unique=True) # 指明真实在数据库创建的字段类型,限制长度,不可重复出现
password = db.Column(db.String(128))
role_id = db.Column(db.Integer, db.ForeignKey("tbl_role.id")) # 指明外键,用于反推
最常见的SQLAlchemy列类型:
字段类型名
|
python中的类型
|
说明
|
Integer
|
int
|
普通整数,一般32位
|
SmallInteger
|
int
|
取值范围小的整数,一般16位
|
BigInteger
|
int或long
|
不限制精度的整数
|
Float
|
float
|
浮点数
|
Numeric
|
decimal.Decimal
|
普通整数,一般32位
|
String
|
str
|
变长字符串
|
Text
|
str
|
变长字符串,对较长或不限长度的字符串做了优化
|
Unicode
|
unicode
|
变长Unicode字符串
|
Unicode Text
|
unicode
|
变长Unicode字符串,对较长或不限长度的字符串做了优化
|
Boolean
|
bool
|
布尔值,在mysql中是tinyint类型
|
Date
|
datetime.date
|
日期
|
Time
|
datetime.time
|
时间
|
DateTime
|
datetime.datetime
|
日期和时间
|
Interval
|
datetime.timedelta
|
时间间隔
|
Enum
|
str
|
一组字符串
|
PickleType
|
任何python对象
|
自动使用Pickle序列化
|
LargeBinary
|
str
|
二进制文件blob
|
DECIMAL(p,d) |
在mysql中常用于保留准确精确度,适用于货币等
|
最常用的SQLAlchemy列选项:
列选项
|
说明
|
primary_key
|
如果为True,代表表的主键
|
unique
|
如果为True,代表这列不允许出现重复的值
|
index
|
如果为True,为这列创建索引,提高查询效率
|
nullable
|
如果为True,允许有空值,如果为Flase,不允许有空值
|
default
|
为这列定义默认值
|
外键四种约束
ForeignKey的参数ondelete
|
说明
|
RESTRICT
|
当父表数据被删除,从表会拒绝删除
|
NO ACTIION
|
同上
|
CASCADE
|
父表数据删除,从表数据也会跟着删除
|
SET NULL
|
父表数据删除,从表外键字段设为NULL
|
关系
class Role(db.Model):
...
users = db.relationship("User", backref="role") class User(db.Model):
...
role_id = db.Column(db.Integer, db.ForeignKey("tbl_role.id"))
常用的SQLAlchemy关系选项:
关系选项名
|
说明
|
backref
|
在关系的另一模型中添加反向引用
|
primaryjoin
|
明确指定两个模型之间使用的联结条件;只需在模棱两可的关系中指定
|
lazy
|
指定如何加载相关记录,可选值有select(首次访问时按需加载)、immediate(源对象加载后加载)、joined(加载记录,但使用联结)、subquery(立即加载,但使用子查询)、noload(永不加载)、dynamic(不加载记录,但提供加载记录的查询)
|
uselist
|
如果为Flase,不使用列表而使用标量值,常用于一对一关系
|
order_by
|
指定关系中记录的排序方式
|
secondary
|
指定多对多中记录的排序方式
|
secondaryjoin
|
在SQLAlchemy中无法自行决定时,指定多对多关系中的二级联结条件
|
数据库操作
创建表
db.create_all()函数将寻找所有db.Model的子类,然后在数据库中创建对应的表。如果数据库中表已经存在,那么db.create_all()不会重新创建或更新相应的表。如果修改模型后要把改动应用到现有的数据库,更新现有数据库表的蛮力方式是先删除旧表再重新创建(不可取)。
db.drop_all() # 清除数据库中所有数据 db.create_all() # 创建所有之前定义的模型类的表
插入行
role1 = Role(name="admin") # 创建Role对象,id是自增的不需要定义
us1 = User(name="wang", password="", role_id=role1.id)
us2 = User(name="zhou", password="", role=role1)
模型的构造函数就受的参数是使用关键字参数指定的模型属性初始值。注User中role属性也可以使用,虽然它不是真正的数据库列,但却是一对多关系的高级表示。无需设定id属性,在多数数据库中主键由数据库自身管理。现在这些对象只存在于python中,还未写入数据库,所以id还未赋值。
对数据库的改动通过数据库会话管理,也称为事务。在Flask-SQLAlchemy中,会话由db.session表示。准备把对象写入数据库之前,要先将其添加到会话。
# 每次只添加一个
db.session.add(role1)
db.session.add(us1)
db.session.add(us2)
# 每次添加多个
db.session.add_all([role1, us1, us2])
添加会话后,再调用db.session.commit()方法提交会话。
db.session.commit()
数据库会话能保证数据库的一致性。提交操作使用原子方式把会话中的对象全部写入数据库。如果在写入会话的过程中发生了错误,那么整个会话都会失效。如果你始终把相关改动放在会话中提交,就能避免因部分更新导致的数据库不一致。
数据库会话也可以回滚,调用db.session.rollback()后,添加到数据库会话中的所有对象都将还原到它们在数据库在中的状态(提交新数据前)。
db.session.rollback()
修改数据行
us2.name = "zhao"
db.session.add(us2)
db.session.commit()
删除行
db.session.delete(us2)
db.session.commit()
查询行
Role.query.all()
User.query.all()
query对象常用的SQLAlchemy查询过滤器:
过滤器
|
说明
|
filter()
|
把过滤器添加到原查询上,返回一个新查询
|
filter_by()
|
把等值过滤器添加到原查询上,返回一个新查询
|
limit
|
指定数值限定原查询返回的结果数量,返回一个新查询
|
offset()
|
偏移原查询返回的结果,返回一个新查询
|
order_by()
|
根据指定条件对原查询结果进行排序,返回一个新查询
|
group_by()
|
根据指定条件对原查询结果进行分组,返回一个新查询
|
query对象最常用的SQLAlchemy查询执行方法:
执行器
|
说明
|
all()
|
以列表形式返回查询的所有结果
|
first()
|
返回查询的第一个结果,如果未查到,返回None
|
first_or_404()
|
返回查询的第一个结果,如果未查到,返回404错误响应
|
get()
|
返回指定主键对应的行,如不存在,返回None
|
get_or_404()
|
返回指定主键对应的行,如不存在,返回404错误响应
|
count()
|
返回查询结果的数量
|
paginate()
|
返回一个Paginate对象,它包含指定范围内的结果
|
one()
|
返回查询的第一个结果,如果未查到,抛出异常
|
one_or_none()
|
返回查询的第一个结果,如果未查到,返回None
|
scalar()
|
返回对应一行一列的查询结果
|
# 通过模型类的query对象
Role.query.all() # 查询多条对象,返回列表
ROle.query.first() # 查询第一个对象
Role.query.get("主键id值") # 查询对应主键值的对象
# 通过数据库会话的query对象
db.session.query(Role).all() # 查询多个实例对象,查询执行方法与上述方式相同
from flask_sqlalchemy import _or User.query.filter_by(name="wang").first().name # 获取通过过滤器后的查询对象的第一个值的name属性
User.query.filter(User.name=="wang", User.role_id==1).first() # 过滤器中逗号表并列关系
User.query.filter(or_(User.name=="wang", User.role_id==1)).first() # or_函数表或关系
User.query.filter(User.role_id.in_([1,2,3])) # in_函数表包含关系
User.query.filter(~User.role_id.in_([1,2,3])) # ~表反
User.query.filter(User.role_id.is_(1)) # is_函数表判断关系
User.query.filter(User.role_id.isnot()) # isnot函数表不为空关系 User.query.offset(2).limit(2).all() # offset跳过两条,从第三条开始,limit取两条 User.query.order_by("-id").all() # 按id排序
User.query.order_by(User.id.desc()).all() # 按id降序的方式排序
User.query.order_by(User.id.asc()).all() # 按id升序的方式排序,默认升序
#以查询内容进行分组,返回新的查询对象
db.session.query(User.role_id, func.count(User.role_id)).group_by(User.role_id).all()
Role.query.get(1).users # 关联查询
User.query.get(1).role # 通过backref对应的字符反向关联查询 users = role1.users # 隐式的查询会调用all()方法
users[0].role
Flask-Migrate实现数据库迁移
创建迁移仓库
from flask_migrate import Migrate
# ...
app = Flask(__name__)
manager = Manager(app) # 创建脚本管理对象
db = SQLAlchemy(app) migrate = Migrate(app, db) # 在flask-script中添加一个db命令,与上面创建的db数据库对象无关
manager.add_command('db', MigrateCommand)
flask db init # 创建migrations文件夹,所有迁移文件都放在里面
创建迁移脚本
更新数据库
flask db upgrade # 上传更改,前进
添加几个迁移
flask db downgrade 版本库 # 删除更改,回退,若无版本号默认回退一步 flask xxx.py db history # 查看历史记录
Flask-SQLAlchemy相关与Flask-Migrate相关的更多相关文章
- Flask – SQLAlchemy成员增加
目录 简介 结构 展示 技术 运行 代码 创建数据库表单 views视图 home主页 添加成员addnew.html 展示页show_all 简介 结构 $ tree -I "__pyca ...
- flask models循环使用和migrate迁移脚本
使用models目的是为了将创建数据库模型的代码与主程序代码分离,migrate的作用就是在数据库字段改变时不用drop表直接做更新操作 新建 models.py exts.py manage.py ...
- python 全栈开发,Day142(flask标准目录结构, flask使用SQLAlchemy,flask离线脚本,flask多app应用,flask-script,flask-migrate,pipreqs)
昨日内容回顾 1. 简述flask上下文管理 - threading.local - 偏函数 - 栈 2. 原生SQL和ORM有什么优缺点? 开发效率: ORM > 原生SQL 执行效率: 原生 ...
- flask SQLAlchemy中一对多的关系实现
SQLAlchemy是Python中比较优秀的orm框架,在SQLAlchemy中定义了多种数据库表的对应关系, 其中一对多是一种比较常见的关系.利用flask sqlalchemy实现一对多的关系如 ...
- flask, SQLAlchemy, sqlite3 实现 RESTful API 的 todo list, 同时支持form操作
flask, SQLAlchemy, sqlite3 实现 RESTful API, 同时支持form操作. 前端与后台的交互都采用json数据格式,原生javascript实现的ajax.其技术要点 ...
- Python利用flask sqlalchemy实现分页效果
Flask-sqlalchemy是关于flask一个针对数据库管理的.文中我们采用一个关于员工显示例子. 首先,我们创建SQLALCHEMY对像db. from flask import Flask, ...
- flask建表遇到的错误: flask,sqlalchemy.exc.OperationalError: (MySQLdb._exceptions.OperationalError) (1071, 'Specified key was too long; max key length is 767 bytes')
error:flask,sqlalchemy.exc.OperationalError: (MySQLdb._exceptions.OperationalError) (1071, 'Specifie ...
- day94:flask:Jinjia2模板引擎&flask中的CSRF攻击&Flask-SQLAlchemy的创建模型类和基本的增删改查
目录 1.Jinjia2模板引擎 1.Jinjia2加载模板并传递数据到模板中 2.Jinjia2的模板语句 3.模板中特有的变量和函数 4.模板中内置的过滤器 5.自定义过滤器 6.模板继承 2.在 ...
- Flask最强攻略 - 跟DragonFire学Flask - 第六篇 Flask 中内置的 Session
Flask中的Session非常的奇怪,他会将你的SessionID存放在客户端的Cookie中,使用起来也非常的奇怪 1. Flask 中 session 是需要 secret_key 的 from ...
- Flask最强攻略 - 跟DragonFire学Flask - 第四篇 Flask 中的模板语言 Jinja2 及 render_template 的深度用法
是时候开始写个前端了,Flask中默认的模板语言是Jinja2 现在我们来一步一步的学习一下 Jinja2 捎带手把 render_template 中留下的疑问解决一下 首先我们要在后端定义几个字符 ...
随机推荐
- P3十进制转换为二进制
#include<stdio.h>int main () { int n; scanf("%d",&n); int a[8]; fo ...
- Jupyter Notebook使用
不论你是刚开始学 Python,还是正在啃数据分析的骨头,对你来说,不断在各种命令行窗口和编辑器里切来切去,或者不断打开各种窗口查看 matplotlib 的输出之类的繁琐操作,一定是家常便饭了.哎呀 ...
- Element-ui 2.8.0版本中提升表格性能,做了哪些事情,原理是什么
背景 项目中一直用element-ui,之前用el-table的时候,发现表格数据较多时,滑动表格就会很卡.我们的表格中只有200行数据,每行大概有30的字段,表格滑动就卡的不行.在Element-u ...
- redis之通信协议
Redis 协议将传输的结构数据分为 5 种最小单元类型,单元结束时统一加上回车换行符号\r\n. 1.单行字符串 以 + 符号开头. 2.多行字符串 以 $ 符号开头,后跟字符串长度. 3.整数值 ...
- mybaties报错:There is no getter for property named 'table' in 'class java.lang.String'
报错是由于xml里获取不到这个table参数 package com.xxx.mapper; import java.util.List; import org.apache.ibatis.annot ...
- MongoDB官方下载安装设置配置文件指定端口号
1.)下载 官网(https://www.mongodb.com/)右上角try free 进入下载中心,下载指定版本 ZIP和MSI随便 如果浏览器下载的慢,可以直接使用下载地址,然后迅雷下 操作 ...
- .NET Core 2.1 以下的控制台应用程序生成 EXE,且使用命令行参数动态运行控制器应用程序的示例
文章: https://stackoverflow.com/questions/44038847/vs2017-compile-netcoreapp-as-exe 引用 <ItemGroup&g ...
- java的递归异常—一个异常可能由另一个异常触发
关键字: Caused by nested exception java.lang.reflect.InvocationTargetException: null at sun.reflect.Nat ...
- StringBuilder.sb.AppendLine();
StringBuilder sb=new StringBuilder(); sb.AppendLine("The world is fair and wonderful.Everything ...
- linq 数据库已存在,直接添加数据
using System.Data.Linq;using System.Data.Linq.Mapping; namespace ConsoleApplication1388{ class Progr ...