from flask_sqlalchemy import SQLAlchemy as BaseSQLAlchemy
from contextlib import contextmanager
#自定义一个SQLAlchemy继承flask_sqlalchemy的,方便自定义方法!!!
class SQLAlchemy(BaseSQLAlchemy):
#利用contextmanager管理器,对try/except语句封装,使用的时候必须和with结合!!!
@contextmanager
def auto_commit_db(self):
try:
yield # <---这里这个yield怎么理解?
self.session.commit()
except Exception as e:
# 加入数据库commit提交失败,必须回滚!!!
self.session.rollback()
raise e
db = SQLAlchemy()
添加数据的时候需要用到with:
with db.auto_commit_db():
user_db = User(nickname=self.nickname, password=self.password)
db.session.add(user_db)
建议深入理解生成器后研究下contextlib的代码,下面简单解释下contextmanager怎么把被修饰对象的 try ... finally ... 分配到with约定的
__enter__
,__exit__
方法中的。contextmanager的使用方式,可见他要求装饰对象是一个生成器
此处yield的作用就是协程切换,如果yield后有值,还可以传出(with 子句 as 后)。
contextmanager 在
__enter__
中第一次调用next(gen)
,代码执行到auto_commit_db
的yield
处转出,执行with
子句的代码contextmanager 在
__exit__
中第二次调用next(gen)
,也就就是with子句结束前执行auto_commit_db的其余部分,完成资源管理的其他任务。