一、数据库连接池
python用于实现数据库连接池的模块是DBUntils
DBUntils有两种模式,一种是PersistentDB,一种是PooledDB
1、PersistentDB
该模式,会为每一个线程创建一个连接,创建的连接只可以给该线程使用,不能给其他线程使用,线程调用close方法后,连接会放到连接池,等待该线程的再次使用,直到线程终止时,连接才会关闭。这个模式,需要自己控制线程数量
# -*-coding:utf-8 -*- import pymysql from DBUtils.PersistentDB import PersistentDB POOL=PersistentDB( creator=pymysql,# 使用链接数据库的模块 maxusage=None, # 一个链接最多被重复使用的次数,None表示无限制 setsession=[], # 开始会话前执行的命令列表。如:["set datestyle to ...", "set time zone ..."] ping=0, # ping MySQL服务端,检查是否服务可用。# 如:0 = None = never, 1 = default = whenever it is requested, 2 = when a cursor is created, 4 = when a query is executed, 7 = always closeable=False,# 如果为False时, conn.close() 实际上被忽略,供下次使用,再线程关闭时,才会自动关闭链接。如果为True时, conn.close()则关闭链接,那么再次调用pool.connection时就会报错,因为已经真的关闭了连接(pool.steady_connection()可以获取一个新的链接) threadlocal=local, # 如果为none,用默认的threading.Loacl对象,否则可以自己封装一个local对象进行替换 host='127.0.0.1', port=3306, user='root', password='root', database='pooldb', charset='utf8' ) def func(): conn=POOL.connection(shareable=False) cursor=conn.cursor() cursor.execute('select * from tb1') result = cursor.fetchall() cursor.close() conn.close() func()
2、PooledDB
该模式下,是创建一批连接到连接池,供所有线程共享使用,一般都推荐用这种模式
# -*-coding:utf-8 -*- import pymysql from DBUtils.PooledDB import PooledDB POOL = PooledDB( creator=pymysql, # 使用链接数据库的模块 maxconnections=6, # 连接池允许的最大连接数,0和None表示不限制连接数 mincached=2, # 初始化时,链接池中至少创建的空闲的链接,0表示不创建 maxcached=5, # 链接池中最多闲置的链接,0和None不限制 maxshared=3, # 链接池中最多共享的链接数量,0和None表示全部共享。PS: 无用,因为pymysql和MySQLdb等模块的 threadsafety都为1,所有值无论设置为多少,_maxcached永远为0,所以永远是所有链接都共享。 blocking=True, # 连接池中如果没有可用连接后,是否阻塞等待。True,等待;False,不等待然后报错 maxusage=None, # 一个链接最多被重复使用的次数,None表示无限制 setsession=[], # 开始会话前执行的命令列表。如:["set datestyle to ...", "set time zone ..."] ping=0, # ping MySQL服务端,检查是否服务可用。# 如:0 = None = never, 1 = default = whenever it is requested, 2 = when a cursor is created, 4 = when a query is executed, 7 = always host='127.0.0.1', port=3306, user='root', password='root', database='pooldb', charset='utf8' ) def func(): conn=POOL.connection(shareable=False) cursor=conn.cursor() cursor.execute('select * from tb1') result = cursor.fetchall() cursor.close() conn.close() func()
二、SQLALchemy
1、简介
定义:SQLAlchemy是一个基于Python实现的ORM框架。提供了SQL工具包及对象关系映射(ORM)工具,该框架建立在 DB API之上,使用关系对象映射进行数据库操作。
本质:将类和对象转换成SQL,然后使用数据库API执行SQL并获取执行结果。
组成部分:
- Engine 框架的引擎
- Connection Pooling 数据库连接池
- Dialect 选择连接数据库的DB API种类
- Schema/Types 架构和类型 SQL Exprression Language,SQL表达式语言
注意:SQLAlchemy本身无法操作数据库,必须依赖pymysql等第三方插件,它不支持修改字段
2、简单使用(执行原生sql)
# -*-coding:utf-8 -*- from sqlalchemy import create_engine import sqlalchemy from sqlalchemy.engine.base import Engine # 生成一个engine对象 engine=create_engine( "mysql+pymysql://root:root@127.0.0.1:3306/flaskdb?charset=utf8", max_overflow=0, # 超过连接池大小外最多创建的连接 pool_size=5, # 连接池大小 pool_timeout=30, # 等待线程池中线程最多等待时间 pool_recycle=-1 #多久对线程池的线程进行重置 ) #创建连接(执行原生sql) conn=engine.raw_connection() # 获取游标对象 cursor=conn.cursor() # 数据库操作 # 创建表 cursor.execute('create table test3 (name char(32),age int)') # 插入数据 cursor.execute('insert into test (name) value(1)') # 删除表 cursor.execute('drop table test') cursor.execute('show tables') res=cursor.fetchall() print(res)
3、orm表创建和表关系
(1)创建表、删除表
# -*-coding:utf-8 -*- import datetime from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarative_base # 导入字段和字段属性 from sqlalchemy import Column,Integer,String,Text,ForeignKey,DateTime,UniqueConstraint,Index # 创建一个基类 Base=declarative_base() # 表模型类 class User(Base): __tablename__='user' # 表名 id=Column(Integer,primary_key=True) #设置为主键 name=Column(String(32),index=True,nullable=False) #不能为空,索引 email=Column(String(32),unique=True) # 唯一 # 注意:datetime.datetime.now不能加括号,加了括号,以后永远是当前时间,不会再改变
# datetime.now:插入数据的时间
# datetime.now(): 程序部署的时间,每条数据时间都是同样,且固定不变的
create_time=Column(DateTime,default=datetime.datetime.now) extra=Column(Text,nullable=True) # __table_args__ 类似django的Meta __table_args__=( UniqueConstraint('id', 'name', name='uix_id_name'), #联合唯一 Index('ix_id_name', 'name', 'email'), #索引 ) def init_db(): engine=create_engine( "mysql+pymysql://root:root@127.0.0.1:3306/flaskdb?charset=utf8", max_overflow=0, pool_size=5, pool_timeout=30, pool_recycle=-1 ) # 通过engine对象来创建表 Base.metadata.create_all(engine) # 删除表 Base.metadata.drop_all(engine) if __name__=='__main__': init_db()
(2)一对多、多对多
# -*-coding:utf-8 -*- from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, String, Integer, ForeignKey from sqlalchemy.engine import create_engine Base = declarative_base() # book和publish 是一对多 class Book(Base): __tablename__ = 'book' id = Column(Integer, primary_key=True) name = Column(String(32), nullable=False) publish_id = Column(Integer, ForeignKey("publish.id")) class Author(Base): __tablename__ = 'author' id = Column(Integer, primary_key=True) name = Column(String(32), nullable=False) class Publish(Base): __tablename__ = 'publish' id = Column(Integer, primary_key=True) name = Column(String(32), nullable=False) #book和auhtor是多对多 class Book2Author(Base): __tablename__ = 'book_author' id = Column(Integer, primary_key=True, autoincrement=True) book_id = Column(Integer, ForeignKey('book.id')) author_id = Column(Integer, ForeignKey('author.id')) def init_db(): engine = create_engine( "mysql+pymysql://root:root@127.0.0.1:3306/flaskdb?charset=utf8", max_overflow=0, pool_size=5, pool_timeout=30, pool_recycle=-1 ) # 通过engine对象来创建表 Base.metadata.create_all(engine) if __name__ == '__main__': init_db()
4、单表基本操作(增删改查)
# -*-coding:utf-8 -*- from sqlalchemy import create_engine from sqlalchemy.sql import text from sqlalchemy.orm import sessionmaker, relationship from model import Author # 生成一个引擎engine engine = create_engine( "mysql+pymysql://root:root@127.0.0.1:3306/flaskdb?charset=utf8", max_overflow=0, pool_size=5, ) # 创建一个会话类 Session = sessionmaker(bind=engine) # 实例化一个会话对象 session = Session() # ------------增-------------- # 创建一个对象 obj1 = Author(name='hello') # # 将对象添加到会话对象中 session.add(obj1) # # 批量增加 session.add_all([ Author(name='ha'), Author(name='ha1'), Author(name='ha2'), ]) session.commit() # ------------删除------------- session.query(Author).filter(Author.id == 1).delete() session.commit() # -------------改-------------- session.query(Author).filter(Author.id>3).update({"name":"nq31"}) # 第二种:类似Django的F查询 # 注意:如果是字符串相加,synchronize_session要设置成False,数字相加则设置成evaluate session.query(Author).filter(Author.id==2).update({Author.name:Author.name+'good'},synchronize_session=False) session.query(Author).filter(Author.id>0).update({"id":Author.id+1},synchronize_session="evaluate") # ------------查--------------- r1=session.query(Author).all() # 对name列进行重命名,只取name列 r2=session.query(Author.name.label('名字'),Author.name).all() # 注意:filter传的是表达式,filter_by传的是参数,first()是只取第一个 r3=session.query(Author).filter(Author.name=='nq31').all() r4=session.query(Author).filter_by(name='nq31').all() r5=session.query(Author).filter_by(name='nq31').first() # 查询id<5,名字为nq31的数据,:value,:name都是占位符 r6=session.query(Author).filter(text("id<:value and name=:name ")).params(value=5,name='nq31').order_by(Author.id).all() # 自定义查询语句 r7 = session.query(Author).from_statement(text("SELECT * FROM Author where name=:name")).params(name='ha1').all() # 返回结果是:[<model.Author object at 0x000001DA49136390>] 类型 session.commit()
注意:查询的返回值是列表,query()的参数如果是表名,则表示获取所有表字段,如果是字段名,则表示只获取该字段
5、数据库高级操作
from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker from model import Author # 生成一个引擎engine engine = create_engine( "mysql+pymysql://root:root@127.0.0.1:3306/flaskdb?charset=utf8", max_overflow=0, pool_size=5, ) # 创建一个会话类 Session = sessionmaker(bind=engine) # 实例化一个会话对象 session = Session() # 条件 res = session.query(Author).filter_by(name='nq31').all() # 表达式,and条件连接 # 查询id>1且名字为nq31的作者 res = session.query(Author).filter(Author.id > 1, Author.name == 'nq31').all() # 查询id在(1,3)之间的作者 res = session.query(Author).filter(Author.id.between(1, 3), Author.name == 'nq31').all() # 注意下划线,in_是取出id为2,3,4的元素 res = session.query(Author).filter(Author.id.in_([2, 3, 4])).all() # # ~非,除 xxx 外 res = session.query(Author).filter(~Author.id.in_([1, 3, 4])).all() # # 二次筛选 也就是嵌套 res = session.query(Author).filter(Author.id.in_(session.query(Author.id).filter_by(name='nq31'))).all() from sqlalchemy import and_, or_ # # or_包裹的都是or条件,and_包裹的都是and条件 # 查询id>3 且 name=nq31的数据 res = session.query(Author).filter(and_(Author.id > 3, Author.name == 'nq31')).all() # 查询id<4 或 name=nq31的数据 res = session.query(Author).filter(or_(Author.id < 4, Author.name == 'nq31')).all() res = session.query(Author).filter( or_( Author.id < 2, and_(Author.name == 'eric', Author.id > 3), # Author.extra != "" )).all() # # 通配符,查询名字以n开头的数据 res = session.query(Author).filter(Author.name.like('n%')).all() # 查询名字不以e开头的数据 res = session.query(Author).filter(~Author.name.like('n%')).all() # # 限制,用于分页,区间 res = session.query(Author)[1:2] # # 排序,根据name降序排列(从大到小) res = session.query(Author).order_by(Author.name.desc()).all() # # 第一个条件重复后,再按第二个条件升序排 res = session.query(Author).order_by(Author.name.desc(), Author.id.asc()).all() # # # 分组 from sqlalchemy.sql import func res = session.query(Author).group_by(Author.name).all() # # 分组之后取最大id,id之和,最小id res = session.query( func.max(Author.id), func.sum(Author.id), func.min(Author.id)).group_by(Author.name).all() # # haviing筛选 res = session.query( func.max(Author.id), func.sum(Author.id), func.min(Author.id)).group_by(Author.name).having(func.min(Author.id) > 2).all()
6、基于scoped_session实现线程安全
(1) 导入scoped_session
from sqlalchemy.orm import scoped_session
(2) 使用方法:
把原来会话类实例化的时候,改成session=scoped_session(Session)
# -*-coding:utf-8 -*- from sqlalchemy.orm import sessionmaker from sqlalchemy import create_engine from sqlalchemy.orm import scoped_session from model import Book engine = create_engine("mysql+pymysql://root:root@127.0.0.1:3306/flaskdb", max_overflow=0, pool_size=5) Session = sessionmaker(bind=engine) # 注意:scoped_session类并没有继承Session,但是,它有session的所有方法 session = scoped_session(Session) obj = Book(name='天行九歌', publish_id=1) session.add(obj) session.commit()
7、多表操作
(1) 模型表
class Book(Base): __tablename__ = 'book' id = Column(Integer, primary_key=True) name = Column(String(32), nullable=False) publish_id = Column(Integer, ForeignKey("publish.id")) # publish字段不会在数据库生成,主要是用来作关联, # relationship(‘关联表类名',backref='反向查询属性’) # 如下,通过book.publish可以拿到publish对象,通过Publish.books可以拿到所有book对象 publish=relationship('Publish',backref='books')class Publish(Base): __tablename__ = 'publish' id = Column(Integer, primary_key=True) name = Column(String(32), nullable=False)
(2)一对多操作
# -*-coding:utf-8 -*- from sqlalchemy.orm import sessionmaker, relationship from sqlalchemy import create_engine from model import Book, Publish engine = create_engine("mysql+pymysql://root:root@127.0.0.1:3306/flaskdb", max_overflow=0, pool_size=5) Session = sessionmaker(bind=engine) session = Session() # --------------添加----------------- # ------第一种------ obj=Publish(name='广州出版社') session.add(obj) b_obj=Book(name='秦时明月',publish_id=3) session.add(b_obj) # ------第二种(前提有设置relationship)------- obj=Book(name='战争',publish=Publish(name='广州出版社')) session.add(obj) # ---------第三种(反向,也需要设置relationship)---------- p_obj=Publish(name='广州出版社') p_obj.book=[Book(name='艺术'),Book(name='蓝图')] session.add(p_obj) # -------------查询--------------- # 1、relationship正向查询 res=session.query(Book).first() print(res.publish.name) print(res.name) # 2、relationship反向查询,根据relationship中backref设置的参数books反查询 res=session.query(Publish).first() for book in res.books: print(book.name) print(res.name) # 根据join来实现链表查询 book_list=session.query(Book,Publish).join(Publish,isouter=True).all() print(book_list) for l in book_list: print(l[0].name,l[1].name) # 根据relationship来链表查询 book_list1=session.query(Book).all() for l in book_list1: print(l.name,l.publish.name) session.commit()
修改跟删除操作跟普通一样
(3)多对多表操作
表模型
class Book(Base): __tablename__ = 'book' id = Column(Integer, primary_key=True) name = Column(String(32), nullable=False) publish_id = Column(Integer, ForeignKey("publish.id")) # publish字段不会在数据库生成,主要是用来作关联, # relationship(‘关联表类名',backref='反向查询属性’) # 如下,通过book.publish可以拿到publish对象,通过Publish.books可以拿到所有book对象 publish=relationship('Publish',backref='books') class Author(Base): __tablename__ = 'author' id = Column(Integer, primary_key=True) name = Column(String(32), nullable=False) # secondary参数是表示通过哪张表关联 books=relationship('Book',secondary='book_author',backref='authors') class Book2Author(Base): __tablename__ = 'book_author' id = Column(Integer, primary_key=True, autoincrement=True) book_id = Column(Integer, ForeignKey('book.id')) author_id = Column(Integer, ForeignKey('author.id'))
操作
# -------------多对多添加------------------ # 1、反向添加 book_obj=Book(name='斗罗大陆') book_obj.authors=[Author(name='唐家三少'),Author(name='唐三')] session.add(book_obj) # 2、正向添加 author_obj=Author(name='三少',books=[Book(name='新世纪',publish_id=1),Book(name='爬虫三件套',publish_id=2)]) session.add(author_obj) # --------------多对多查询-------------- # 1、反向查询 res=session.query(Book).first() for r in res.authors: print(r.name) # 2、正向查询 res=session.query(Author).first() for r in res.books: print(r.name) # 1、基于对象查询 res=session.query(Author).filter(Author.name=='唐家三少').all() #all返回的是列表 for r in res[0].books: print(r.name) # 2、基于链表查询 '''原生sql语句 select Book.name from Book inner join Author on Author.id=Book2Author.author_id inner join Book2Author on Book.id=Book2Author.id where Author.name='唐家三少' ''' res=session.query(Book.name).join(Book2Author).join(Author).filter(Book2Author.book_id==Book.id,Book2Author.author_id==Author.id,Author.name=='唐家三少').all() for r in res: print(r.name)
(4)其他操作
# 连表 res=session.query(Book,Publish).filter(Book.publish_id==Publish.id).all() ''' join连表 join()括号内放连表条件,也就是原生sql语句中on后面的条件 注意:默认是inner join ,如果isouter=True 则表示左连接,left join,没有右连接,可以两个表位置交换一下,来实现右链接 ''' res=session.query(Book).join(Publish).all() for r in res: print(r.name,r.publish.name,r.id) res=session.query(Book).join(Publish,Book.publish_id==Publish.id,isouter=True).all() for r in res: print(r.name,r.publish.name,r.id) ''' union用于合并两个或多个结果集合 union和union_all区别: union:不包括重复行,会按默认规则排序 union_all:包括重复行,不进行排序 ''' res1=session.query(Book.name).filter(Book.id<4) res2=session.query(Publish.name).filter(Publish.id<3) res=res1.union(res2).all() print(res) r=res1.union_all(res2).all() print(r)
三、Flask-SQLAlchemy
1、简介
Flask_SQLAlchemy是基于SQLAlchemy开发的扩展组件,也是ORM框架
安装:pip install flask-sqlalchemy
2、配置
说明 | |
---|---|
SQLALCHEMY_DATABASE_URI |
连接数据库。示例:mysql://username:password@host/post/db?charset=utf-8 |
SQLALCHEMY_BINDS |
一个将会绑定多种数据库的字典。 更多详细信息请看官文 |
SQLALCHEMY_ECHO |
调试设置为true |
SQLALCHEMY_POOL_SIZE |
数据库池的大小,默认值为5。 |
SQLALCHEMY_POOL_TIMEOUT |
连接超时时间 |
SQLALCHEMY_POOL_RECYCLE |
自动回收连接的秒数。 |
SQLALCHEMY_MAX_OVERFLOW |
控制在连接池达到最大值后可以创建的连接数。当这些额外的 连接回收到连接池后将会被断开和抛弃。 |
SQLALCHEMY_TRACK_MODIFICATIONS |
3、连接数据库
# -*-coding:utf-8 -*- from flask import Flask from flask_sqlalchemy import SQLAlchemy app=Flask(__name__) # mysql+pymysql://用户名:密码@127.0.0.1:3306/数据库 DB_URI='mysql+pymysql://root:root@127.0.0.1:3306/flaskdb?charset=utf8mb4' app.config['SQLALCHEMY_DATABASE_URI']=DB_URI app.config['SQLALCHEMY_TRACK_MODIFICATIONS']=False # SQLALCHEMY_TRACK_MODIFICATIONS这个配置变量决定是否追踪对象的修改,这用于FLask- SQLALchemy的事件通知系统。这个配置键默认值为None,如果没有特殊需要我们把它设置为Flase, 避免造成一些没必要的性能浪费 db=SQLAlchemy(app)
4、数据库模型类中字段和参数
4.1、表名指定
class Book(Base): __tablename__ = 'book' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(32), nullable=False)
__tablename__:用来指定表名,如果没有写__tablename__,则默认将类名转为小写,作为表名
注意:如果类名是多个单词,则转为小写后并使用下划线分隔,如: BookAuhtor类 - ->book_author
db.Colunm:表示字段
4.2、常用字段类型表
说明 | 映射到数据库对应类型 | |
---|---|---|
Integer | 整数 | int类型 |
String | 字符串,String 类内可选择length 参数的值用于设置最大字符个数 |
varchar类型 |
Text | 用于储存较长的Unicode文本,,理论上可以储存65535个字节 | text类型 |
Date | 日期,存储Python 的datetime.date 对象 |
date类型 |
Time | 时间,存储Python 的datetime.time 对象 |
time类型 |
DateTime | 时间和日期,存储Python 的datetime 对象 |
datetime类型 |
Float | 浮点类型 | float类型 |
Double | 双精度浮点类型,比浮点类型小数位精度更高。 | double类型,占据64位。 |
Boolean | 布尔值 | tinyint类型 |
Enum | 枚举类型 |
4.3、Column常用参数表
说明 | |
---|---|
primary_key | 如果设为True,该列就是表的主键 |
unique | 如果设为True,该列每个值唯一,也就是该字段不允许出现重复值 |
index | 如果设为True,为这列创建索引,用于提升查询效率 |
nullable | 如果设为True,这列允许使用空值,反之则不允许使用空值。 |
server_default | 为这列定义默认值, 默认值只支持字符串,其他类型需要db.text()方法指定 |
default | 为这列定义默认值,但是该约束并不会真正映射到表结构中,该约束只会在ORM层面实现(不推荐使用) |
comment | 该字段的注释 |
name | 可以使用该参数直接指定字段名 |
autoincrement |
上表中server_default的常用配置如下:
配置默认值类型 | 代码 |
---|---|
更新datatime时间 | server_default = db.text("CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP") |
当前的datatime时间 | server_default = db.text("CURRENT_TIMESTAMP") |
数字 | server_default=“数字” |
布尔 | server_default=db.text('True') / server_default=db.text('False')/ server_default='数字' |
5、数据库操作
5.1、建表
# -*-coding:utf-8 -*- from flask import Flask from flask_sqlalchemy import SQLAlchemy app = Flask(__name__) # mysql+pymysql://用户名:密码@127.0.0.1:3306/数据库 DB_URI = 'mysql+pymysql://root:root@127.0.0.1:3306/flaskdb?charset=utf8mb4' app.config['SQLALCHEMY_DATABASE_URI'] = DB_URI app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False # SQLALCHEMY_TRACK_MODIFICATIONS这个配置变量决定是否追踪对象的修改,这用于FLask- SQLALchemy的事件通知系统。这个配置键默认值为None,如果没有特殊需要我们把它设置为Flase, 避免造成一些没必要的性能浪费 db = SQLAlchemy(app) class UserInfo(db.Model): id = db.Column(db.Integer, primary_key=True, autoincrement=True) username = db.Column(db.String(20), nullable=False) class School(db.Model): __tablename__="school" id = db.Column(db.Integer,primary_key=True,nullable=False,autoincrement=True,comment='ID') name = db.Column(db.String(30),nullable=False,server_default='',comment='学校名称') area=db.Column(db.String(30),nullable=False,server_default='广州',comment='学校地址') # 默认参数‘广州’ score=db.Column(db.Integer,nullable=False,server_default='100') # 默认参数 100 # 创建所有库 db.create_all() # 删除所有库 db.drop_all()
5.2、增删改查
常用的过滤器
过滤器 | 说明 |
---|---|
filter() | 使用指定的规则过滤记录相当于sql的where约束条件,返回一个新查询 |
filter_by() | 同filter原理,不同的是查询的时要使用关键字参数,返回一个新查询 |
limit() | 使用指定的值限制原查询返回的结果的数量,返回一个新查询 |
offset() | 偏移原查询返回的结果,返回一个新查询 |
order_by() | 根据指定条件对原查询结构进行排序,返回一个新查询 |
group_by() | 根据指定条件对原来查询结构进行分组,返回一个新查询 |
(1) 增加
school01=School(name='北京大学',area='北京',score=100) school02=School(name='北京大学',area='北京',score=100) # 增加单条数据 用add db.session.add(school01) # 增加多条数据 用add_all db.session.add_all([school01,school02])
db.session.commit()
(2)查询
# all() 获取所有结果 school=School.query.all() # first() 获取第一个结果 school=School.query.first() # get() 返回指定主键值(id字段)的记录 school=School.query.get(3) # filter()过滤,相当于where约束条件 school=School.query.filter(School.area=='北京').all() # filter_by: 通filter一样,它使用的是关键字参数查询,不能用在多表查询 school=School.query.filter_by(area='北京').all() #db.session.query(模型类,也就是表类)可以进行多表查询 obj=db.session.query(School).filter(School.name=='北京大学').first()
(3)修改
# 更改,先找到更改对象,修改对象的属性就可以 obj=School.query.filter(School.area=='北京').first() obj.score=700 db.session.commit()
(4)删除
同样,也是先找到对象,然后调用db.session.delete(对象)删除
obj= School.query.filter(School.name=='北京大学').first() db.session.delete(obj) db.session.commit()
总结:flask_sqlalchemy用法总体跟sqlalchemy很类似。
为了解决每次更新模型,都需要先删除原来的模型表,导致原来数据被删除的问题,可以使用flask-migrate扩展组件来解决
四、flask-migrate
1、flask-migrate基本使用方法
(1)先安装
pip install flask-migrate
(2)具体使用案例,manage.py文件如下:
注意:flask-migrate需要和flask-script配合使用
# -*-coding:utf-8 -*- # 导入Migrate,MigrateCommand模块 from flask_migrate import Migrate,MigrateCommand from flask_sqlalchemy import SQLAlchemy from flask import Flask from flask_script import Manager app = Flask(__name__) DB_URI = 'mysql+pymysql://root:root@127.0.0.1:3306/flaskdb?charset=utf8mb4' app.config['SQLALCHEMY_DATABASE_URI'] = DB_URI app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False db = SQLAlchemy(app) manager=Manager(app) # Migrate()第一个参数是flask实例,第二个参数SQLAlchemy数据库实例 Migrate(app,db) # 在manager实例中添加db 子命令) manager.add_command('db',MigrateCommand) # 定义模型类 class School1(db.Model): __tablename__="school1" id = db.Column(db.Integer,primary_key=True,nullable=False,autoincrement=True,comment='ID') name = db.Column(db.String(30),nullable=False,server_default='',comment='学校名称') area=db.Column(db.String(30),nullable=False,server_default='广州',comment='学校地址') # 默认参数‘广州’ score=db.Column(db.Integer,nullable=False,server_default='100') # 默认参数 100 if __name__=='__main__': manager.run()
2、flask-migrate具体命令
注意:切入到manage.py所在目录中,就可以执行以下命令
2.1、初始化,只执行一次,创建migrations文件夹
#命令格式:python 文件 自定义的命令 init, # manager.add_command('db',MigrateCommand),db就是自定义命令 python manage.py db init
2.2、创建迁移文件,等同于Django中 makemigartions
python manage.py db migrate # python manage.py db migrate -m '注释信息'
2.3、更新数据库,等同于Django中migrate
python manage.py db upgrade # 注意:upgrade 是将改动迁移到数据库中
2.4、回退版本
# 1、查看历史版本 python manage.py db history # 返回:<base> -> 95afb6893815 (head), empty message # 2、回退到指定的版本 python manage.py db downgrade 95afb6893815(版本号)
'