关于python peewee的事务回滚用法


发现python peewee的资料相比sqlalchemy来说真心少呀,于是乎为了让这两个orm有竞争产生发展,我决定多写点peewee的文档.    还有一方面是官方的docs文档有些地方说的不明不白的。 虽然大部分功能都给出了样例代码,但对于有些的场景光看docs文档是不够的.  上次说了peewee ForeignKeyField外键, 这次就写下peewee 事务方面的文档。 简单说, peewee对数据库事务处理封装了几个模式,有with关键词,装饰器,普通模式. 


该文章写的有些乱,欢迎来喷 ! 另外文章后续不断更新中,请到原文地址查看更新。

http://xiaorui.cc/2016/02/18/%E5%85%B3%E4%BA%8Epython-peewee%E7%9A%84%E4%BA%8B%E5%8A%A1%E5%9B%9E%E6%BB%9A%E7%94%A8%E6%B3%95/

.

在这之前,我们要还是需要看下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… …


大家觉得文章对你有些作用! 如果想赏钱,可以用微信扫描下面的二维码,感谢!
另外再次标注博客原地址  xiaorui.cc

发表评论

电子邮件地址不会被公开。 必填项已用*标注