发现python peewee的资料相比sqlalchemy来说真心少呀,于是乎为了让这两个orm有竞争产生发展,我决定多写点peewee的文档. 还有一方面是官方的docs文档有些地方说的不明不白的。 虽然大部分功能都给出了样例代码,但对于有些的场景光看docs文档是不够的. 上次说了peewee ForeignKeyField外键, 这次就写下peewee 事务方面的文档。 简单说, peewee对数据库事务处理封装了几个模式,有with关键词,装饰器,普通模式.
该文章写的有些乱,欢迎来喷 ! 另外文章后续不断更新中,请到原文地址查看更新。
.
在这之前,我们要还是需要看下peewee关于事务方面的代码。 我们可以发现MySQLDatabase默认就把for_update配置为True,另外父类Database有autocommit参数,用来开启事务.
#blog: xiaorui.cc class MySQLDatabase(Database): #Database subclass that works with either “MySQLdb” or “pymysql”. commit_select = True compound_operations = ['UNION'] for_update = True subquery_delete_same_table = False class Database(): def __init__(self, database, threadlocals=True, autocommit=True, fields=None, ops=None, autorollback=False, use_speedups=True, **connect_kwargs): ... def begin(self): pass def commit(self): #提交事务 self.get_conn().commit() def rollback(self): # 回滚 self.get_conn().rollback() def set_autocommit(self, autocommit): #设置autocommit状态,值为False,True self.__local.autocommit = autocommit def get_autocommit(self): #获取autocommit状态. if self.__local.autocommit is None: self.set_autocommit(self.autocommit) return self.__local.autocommit class _atomic(_callable_context_manager): # 装饰器的模式处理事务逻辑. def __init__(self, db): self.db = db def __enter__(self): if self.db.transaction_depth() == 0: self._helper = self.db.transaction() else: self._helper = self.db.savepoint() return self._helper.__enter__() def __exit__(self, exc_type, exc_val, exc_tb): return self._helper.__exit__(exc_type, exc_val, exc_tb) class transaction(_callable_context_manager): def __init__(self, db): self.db = db def _begin(self): self.db.begin() def commit(self, begin=True): self.db.commit() if begin: self._begin() def rollback(self, begin=True): self.db.rollback() if begin: self._begin() def __enter__(self): self._orig = self.db.get_autocommit() self.db.set_autocommit(False) if self.db.transaction_depth() == 0: self._begin() self.db.push_transaction(self) return self def __exit__(self, exc_type, exc_val, exc_tb): try: if exc_type: self.rollback(False) elif self.db.transaction_depth() == 1: try: self.commit(False) except: self.rollback(False) raise finally: self.db.set_autocommit(self._orig) self.db.pop_transaction()
下面的模式是with关键词模式,db.atomic()对接了with模式。
#blog: xiaorui.cc from peewee import * db = MySQLDatabase("rui", user = "root", passwd = "xiaorui.cc",autocommit=False) try: with db.atomic(): user = User.create(username=username) return 'Success' except peewee.IntegrityError: return 'Failure: %s is already in use.' % username
下面是装饰器的模式.
#blog: xiaorui.cc @db.atomic() def create_user(username): return User.create(username=username) create_user('liming')
手动自动提交模式
默认情况下,数据库是用自动提交的,我们可以在构造db对象的时候控制autocommit,或者可以通过set_autocommit()进行后续配置是否开启事物.
如果你选择禁用自动提交,那么你必须显式地调用数据库。要使用 begin()开始一个事务,并提交或回滚。
下面的行为跟上面的的上下文管理器和装饰类似:
这是peewee docs里面的例子:
#xiaorui.cc db.set_autocommit(False) db.begin() try: user.delete_instance(recursive=True) except: db.rollback() raise else: try: db.commit() except: db.rollback() raise finally: db.set_autocommit(True)
这例子相对整洁干净. roolback() 是回滚函数,commit() 提交事务的修改.
#blog: xiaorui.cc db = MySQLDatabase("rui", user = "root", passwd = "xiaorui.cc",autocommit=False) db.begin() User.create(username='somebody') db.commit()
更详细的peewee事务操作方面的文档,请参考 http://docs.peewee-orm.com/en/latest/peewee/transactions.html
END… …