网上关于django1.6的事务资料不少,可是1.8的却搜不到任何资料,本身要用的时候费了很多劲就是不行,如今记下要用的人少走弯路 version:Django 1.8 事务官方文档 事务中文文档 里面介绍不少方法,不一一赘述,按照文档便可,下面只分析下atomic方法的源码 按照官方文档 transaction.atomic 有两种用法装饰器和上下文管理器html
# atomic() 方法 # from django.db import transaction ################### # atomic() ################### def atomic(using=None, savepoint=True): # 装饰器和上下文管理器必须.()调用方法,由于真正的处理是该方法返回的实例,不是该方法自己 if callable(using): return Atomic(DEFAULT_DB_ALIAS, savepoint)(using) # Decorator: @atomic(...) or context manager: with atomic(...): ... else: return Atomic(using, savepoint) ########################################## # Atomic类 省略了非核心内容 ############################################ class Atomic(ContextDecorator): def __init__(self, using, savepoint): self.using = using self.savepoint = savepoint def __enter__(self): connection = get_connection(self.using) sid = connection.savepoint() # 进入with建立一个保存点 # .............do def __exit__(self, exc_type, exc_value, traceback): if connection.in_atomic_block: # do............. if sid is not None: try: connection.savepoint_commit(sid) # 提交事务 except DatabaseError: try: connection.savepoint_rollback(sid) # 捕获数据库异常回滚 connection.savepoint_commit(sid) except Error: connection.needs_rollback = True raise ## 还有一段代码是exec_type收到其余程序异常时候 全局回滚,此处省略 # do................. ############################### # ContextDecorator ################################# class ContextDecorator(object): def __call__(self, func): def inner(*args, **kwargs): with self: # 把函数放进self的with上下文管理器,效果with相同,只是控制细粒度不一样 return func(*args, **kwargs) return inner
class Tran(): def __init__(self, conn=None, close=True): if conn is None: # 建立数据库连接 print 'init' self.conn = conn_tbkt() self.cur = self.conn.cursor() self.sql = [] def __enter__(self): # 上下文管理器返回 sql语句列表 with Tran('tbkt_pxb') as sqls: print 'enter' return self.sql # sql.append('select 1') def __exit__(self, exc_type, exc_val, exc_tb): print 'exit' try: print self.sql # 执行sql for s in self.sql: self.cur.execute(s) self.conn.commit() except: # 能够捕获全部异常(django事务若是中间出现程序异常终止没法回滚) try: # 回滚自己也是sql执行,也有可能失败 import traceback traceback.print_exc() print 'rollback' self.conn.rollback() except: print u'回滚失败' finally: self.cur.close() self.conn.close()
# 在事务块中@atomic() 或者 with atomic(): sid = transaction.savepoint('tbkt_pxb') try: # do .......... except: transaction.savepoint_rollback(sid, 'tbkt_pxb')
注意:若是有多个数据库有路由,则须要指定和路由返回一致的useing: math2下的model须要事务,即便ziyuan_new和default是同一个库,也必须使用useing=ziyuan_newpython
ziyuan_app = ['math2', 'ziyuan'] if model._meta.app_label in ziyuan_app: return "ziyuan_new" return 'default'
调用时候必须.()方法调用sql
atomic块中必须注意try的使用,若是手动捕获了程序错误会致使atomic包装器捕获不到异常,也就不会回滚。要么try内代码不影响事务操做,要么就捕获异常后raise出,让atomic能够正常回滚(就是由于没有注意到这个问题,致使尝试了好几天都没成功,切记)数据库