Flask (三) 数据迁移
数据迁移
安装
pip install flask-migrate
初始化
使用app和db进行migrate对象初始化
from flask_migrate import Migrate
migrate = Migrate()
migrate.init_app(app=app, db=db)
安装了flask-script后,可以在manager上添加迁移指令
from flask_migrate import MigrateCommand
manager.add_command('db', MigrateCommand)
操作
python manager.py db init 只调用一次, 这里的db是添加命令时给定的名称
python manager.py db migrate 生成迁移文件
python manager.py db upgrade 执行迁移中的升级
python manager.py db downgrade 执行迁移中的降级
模型进阶
创建模型
# 模型:类
class Person(db.Model):
__tablename__ = 'person'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String(20), unique=True)
age = db.Column(db.Integer, default=1)
字段类型
| 类型名 | Python类型 | 说 明 |
|---|---|---|
| Integer | int | 普通整数,一般是 32 位 |
| SmallInteger | int | 取值范围小的整数,一般是 16 位 |
| BigInteger | int 或 long | 不限制精度的整数 |
| Float | float | 浮点数 |
| Numeric | decimal.Decimal | 定点数 |
| String | str | 变长字符串 |
| Text | str | 变长字符串,对较长或不限长度的字符串做了优化 |
| Unicode | unicode | 变长 Unicode 字符串 |
| UnicodeText | unicode | 变长 Unicode 字符串,对较长或不限长度的字符串做了优化 |
| Boolean | bool | 布尔值 |
| Date | datetime.date | 日期 |
| Time | datetime.time | 时间 |
| DateTime | datetime.datetime | 日期和时间 |
| Interval | datetime.timedelta | 时间间隔 |
| LargeBinary | str | 二进制文件 |
常用约束
| 选项名 | 说 明 |
|---|---|
| primary_key | 如果设为 True ,这列就是表的主键 |
| unique | 如果设为 True ,这列不允许出现重复的值 |
| index | 如果设为 True ,为这列创建索引,提升查询效率 |
| nullable | 如果设为 True ,这列允许使用空值;如果设为 False ,这列不允许使用空值 |
| default | 为这列定义默认值 |
模型操作
单表操作
增加数据
a. 一次增加一条数据:
p = Person()
p.name = '小明'
p.age = 22
try:
db.session.add(p)
db.session.commit()
except:
# 回滚
db.session.rollback()
db.session.flush()
b. 一次添加多条数据
persons = []
for i in range(10,30):
p = Person()
p.name = '宝强' + str(i)
p.age = i
persons.append(p)
db.session.add_all(persons)
db.session.commit()
删除数据
p = Person.query.first() # 获取第一条数据
db.session.delete(p)
db.session.commit()
修改数据
p = Person.query.first()
p.age = 100
db.session.commit()
查询数据
过滤器
filter() 把过滤器添加到原查询上,返回一个新查询
filter_by() 把等值过滤器添加到原查询上,返回一个新查询
limit() 使用指定的值限制原查询返回的结果数量,返回一个新查询
offset() 偏移原查询返回的结果,返回一个新查询
order_by() 根据指定条件对原查询结果进行排序,返回一个新查询
group_by() 根据指定条件对原查询结果进行分组,返回一个新查询
常用查询
all() 以列表形式返回查询的所有结果
first() 返回查询的第一个结果,如果没有结果,则返回 None
first_or_404() 返回查询的第一个结果,如果没有结果,则终止请求,返回 404 错误响应
get() 返回指定主键对应的行,如果没有对应的行,则返回 None
get_or_404() 返回指定主键对应的行,如果没找到指定的主键,则终止请求,返回 404 错误响应
count() 返回查询结果的数量
paginate() 返回一个 Paginate 对象,它包含指定范围内的结果
查询属性
contains
startswith
endswith
in_
__gt__
__ge__
__lt__
__le__
逻辑运算
与 and_
filter(and_(条件),条件…)
或 or_
filter(or_(条件),条件…)
非 not_
filter(not_(条件),条件…)
示例:
查询:
persons = Person.query.all() # 获取所有
persons = Person.query.filter(Person.age>22)
# filter功能比filter_by强大
persons = Person.query.filter(Person.age==22) # filter(类.属性==值)
persons = Person.query.filter_by(age=22) # filter_by(属性=值)
persons = Person.query.filter(Person.age.__lt__(22)) # <
persons = Person.query.filter(Person.age.__le__(22)) # <=
persons = Person.query.filter(Person.age.__gt__(22)) # >
persons = Person.query.filter(Person.age.__ge__(22)) # >=
persons = Person.query.filter(Person.age.startswith('宝')) # 开头匹配
persons = Person.query.filter(Person.age.endswith('宝')) # 结尾匹配
persons = Person.query.filter(Person.age.contains('宝')) # 包含
persons = Person.query.filter(Person.age.in_([11,12,22])) # in_
persons = Person.query.filter(Person.age>=20, Person.age<30) # and_
persons = Person.query.filter(and_(Person.age>=20, Person.age<30)) # and_
persons = Person.query.filter(or_(Person.age>=30, Person.age<20)) # or_
persons = Person.query.filter(not_(Person.age<30)) # not_
排序:
persons = Person.query.limit(5) # 取前5个
persons = Person.query.order_by('age') # 升序
persons = Person.query.order_by('-age') # 降序
persons = Person.query.order_by(desc('age')) # 降序
persons = Person.query.offset(5) # 跳过前5个
分页:
# 获取页码page和每页数量num
page = int(request.args.get('page'))
num = int(request.args.get('num'))
# 手动做分页
persons = Person.query.offset((page-1) * num).limit(num)
# 使用paginate做分页
persons = Person.query.paginate(page, num, False).items
paginate对象的属性:
items:返回当前页的内容列表
has_next:是否还有下一页
has_prev:是否还有上一页
next(error_out=False):返回下一页的Pagination对象
prev(error_out=False):返回上一页的Pagination对象
page:当前页的页码(从1开始)
pages:总页数
per_page:每页显示的数量
prev_num:上一页页码数
next_num:下一页页码数
query:返回创建该Pagination对象的查询对象
total:查询返回的记录总数
多表关联
一对多
# 一对多
class Grade(db.Model):
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String(16))
# 定义班级标的一对多关系,不是字段, Student为学生表模型, backref为反向查找名称
students = db.relationship('Student', backref='grade1', lazy=True)
class Student(db.Model):
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String(16))
age = db.Column(db.Integer, default=1)
# 创建外键,关联到班级表的主键,实现一对多关系,班级表中也要有对应操作
grade = db.Column(db.Integer, db.ForeignKey(Grade.id))
查:
# 获取学生的所在班级信息(反向)
stu = Student.query.get(stuid)
grade = stu.stus
# 获取班级的所有学生 (正向)
grade = Grade.query.get(gradeid)
students = grade.students
删:
# 删除班级后, 学生的grade字段会变为null
grade = Grade.query.get(id)
db.session.delete(grade)
db.session.commit()
多对多
用户收藏电影,一个用户可以收藏多部电影, 一部电影可以被不同的用户收藏, 是一个多对多关系.
# 中间表(不是模型)
collects = db.Table('collects',
# user_id为表字段名称, user.id为外键表的id
db.Column('user_id', db.Integer, db.ForeignKey('user.id'), primary_key=True),
db.Column('movie_id', db.Integer, db.ForeignKey('movie.id'), primary_key=True)
)
class Movie(db.Model):
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String(200))
class User(db.Model):
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String(16))
age = db.Column(db.Integer, default=1)
# 多对多 关联的学生表格的模型, 中间表的名称, 反向查找
movies = db.relationship('Movie', backref='users', secondary=collects, lazy='dynamic')
lazy属性:
懒加载,可以延迟在使用关联属性的时候才建立关联
lazy='dynamic': 会返回一个query对象(查询集),可以继续使用其他查询方法,如all().
lazy='select': 首次访问到属性的时候,就会全部加载该属性的数据.
lazy='joined': 在对关联的两个表进行join操作,从而获取到所有相关的对象
lazy=True: 返回一个可用的列表对象,同select
查:
# 查询用户收藏的所有电影
user = User.query.get(id)
movies = user.movies
# 查询电影被哪些用户收藏
movie = Movie.query.get(id)
users = movie.users
删:
# 中间表的数据会被级联删除
movie = Movie.query.get(id)
db.session.delete(movie)
db.session.commit()
增:
# 用户收藏电影
user = User.query.get(id)
movie = Movie.query.get(id)
user.movies.append(movie)
db.session.commit()
Flask (三) 数据迁移的更多相关文章
- codefirst数据迁移技术,在保留数据库数据下实现对模型的修改并映射到数据库
一前言 这是我的处女作,写的不好的地方还望指出共同讨论.EF的数据访问方式有三种DbFirst,ModelFirst,还有本文要提到的CodeFirst 三者都是以ORM的方式建立.本人之前学习的.n ...
- Flask入门之触发器,事件,数据迁移
SQLAlchemy Core和SQLAlchemy ORM都具有各种各样的事件挂钩: 核心事件 - 这些在 Core Events中描述,并包括特定于连接池生命周期,SQL语句执行,事务生命周期以及 ...
- Docker数据卷Volume实现文件共享、数据迁移备份(三)--技术流ken
前言 前面已经写了两篇关于docker的博文了,在工作中有关docker的基本操作已经基本讲解完了.相信现在大家已经能够熟练配置docker以及使用docker来创建镜像以及容器了.本篇博客将会讲解如 ...
- Docker数据卷Volume实现文件共享、数据迁移备份(三)
数据卷volume功能特性 数据卷 是一个可供一个或多个容器使用的特殊目录,实现让容器中的一个目录和宿主机中的一个文件或者目录进行绑定.数据卷 是被设计用来持久化数据的对于数据卷你可以理解为NFS中的 ...
- 生产环境下,oracle不同用户间的数据迁移。第三部分
任务名称:生产环境下schema ELON数据迁移至schema TIAN########################################前期准备:1:确认ELON用户下的对象状态se ...
- MySQL数据迁移到SQL Server
数据迁移的工具有很多,基本SSMA团队已经考虑到其他数据库到SQL Server迁移的需求了,所以已经开发了相关的迁移工具来支持. 此博客主要介绍MySQL到SQL Server数据迁移的工具:SQL ...
- 从零自学Hadoop(16):Hive数据导入导出,集群数据迁移上
阅读目录 序 导入文件到Hive 将其他表的查询结果导入表 动态分区插入 将SQL语句的值插入到表中 模拟数据文件下载 系列索引 本文版权归mephisto和博客园共有,欢迎转载,但须保留此段声明,并 ...
- 从零自学Hadoop(17):Hive数据导入导出,集群数据迁移下
阅读目录 序 将查询的结果写入文件系统 集群数据迁移一 集群数据迁移二 系列索引 本文版权归mephisto和博客园共有,欢迎转载,但须保留此段声明,并给出原文链接,谢谢合作. 文章是哥(mephis ...
- SQL SERVER几种数据迁移/导出导入的实践
SQLServer提供了多种数据导出导入的工具和方法,在此,分享我实践的经验(只涉及数据库与Excel.数据库与文本文件.数据库与数据库之间的导出导入). (一)数据库与Excel 方法1: 使用数据 ...
随机推荐
- LightOJ1214 Large Division —— 大数求模
题目链接:https://vjudge.net/problem/LightOJ-1214 1214 - Large Division PDF (English) Statistics Forum ...
- RobotFramework教程使用笔记——RobotFramework的安装配置
(一) Python的安装和pip配置 首先,从Python的官方网站 www.python.org http://www.python.org/ftp/python 然后,运行下载的MSI安装包, ...
- Java接口测试之使用有道翻译API
写接口测试框架,找了有道翻译API来当测试数据 package com.httpGetTest; import java.beans.Encoder; import java.net.URLEncod ...
- 2U网络机箱的尺寸是多少,4U网络机箱的尺寸是多少
厚度以4.445cm为基本单位.1U就是4.445cm,2U则是1U的2倍为8.89cm.48.26cm=19英寸,如果是标准的机架式设备,宽应该是满足这个标准的.纵深的话 有600mm或者800mm ...
- js日期和时间戳互换
<script> function js_strto_time(str_time){ var new_str = str_time.replace(/:/g,'-'); new_str = ...
- Java 高阶 —— native 关键字与 JNI
1. JNI Java中JNI的使用详解第一篇:HelloWorld JNI:Java Native Interface,Java 本地接口(或本机接口,更具体地讲叫本地编程接口),其提供了若干 AP ...
- Learning ReactNative (一) : JavaScript模块基本原理与用法
在使用ReactNative进行开发的时候,我们的工程是模块化进行组织的.在npmjs.com几十万个库中,大部分都是遵循着CommonJS规则的.在ES6中引入了class的概念,从此JavaScr ...
- SecureCRT rz上传文件失败
SecureCRT 将 Windows 上的文件传至 Linux 端,小的文件没有问题能够正常上传,但是对于几百M的文件往往上传过程中失败. 解决办法:使用 rz -be,并且去掉对话框中" ...
- JAVA中的BIO,NIO,AIO
在了解BIO,NIO,AIO之前先了解一下IO的几个概念: 1.同步 用户进程触发IO操作并等待或者轮询的去查看IO操作是否就绪, 例如自己亲自出马持银行卡到银行取钱 2.异步 用户触发IO操作以后, ...
- 启动Android模拟器问题集锦
1.新建AVD时,报错“no CPU/ABI system image available for this target”, 解决:在SDK Manager中下载System Image 2.Sys ...