首先,this GitHub project包含了我在这篇文章中讨论和询问的代码。这是一个非专有的、简短的示例,说明了我的团队正在进行的工作。在
我在一个项目中使用Django数据库事务对表进行更新,准备转换为可用于商业目的的XML。我们通过使用transaction.atomic()上下文管理器修复了以前损坏的代码,以确保错误得到正确处理。每个UPDATE语句位于上下文管理器中,而上下文管理器又位于函数中。在程序中的另一个函数(set_yes(),set_no(),和broken_query())中有三个函数被调用:
models.pyfrom __future__ import unicode_literals
from django.db import connection, DatabaseError, transaction
import pandas as pd
from django.db import models
class TestTable(models.Model):
value1 = models.IntegerField()
value2 = models.IntegerField()
same = models.CharField(max_length=3, null=True)
def setup_table():
"""
sets up the basic table.
several rows will have matching values, some won't.
:return: None
"""
row1 = TestTable(value1=1, value2=1)
row1.save()
row2 = TestTable(value1=2, value2=1)
row2.save()
row3 = TestTable(value1=56, value2=1)
row3.save()
row4 = TestTable(value1=10, value2=10)
row4.save()
def set_yes():
"""
sets "same" column on rows with matching value1 and value2 columns to "yes"
:return: None
"""
query = '''
UPDATE db_app_testtable
SET same = 'yes'
WHERE value1 = value2
'''
try:
with transaction.atomic():
cursor = connection.cursor()
cursor.execute(query)
except DatabaseError as ex:
print "set_yes has error %s" % (ex)
raise
finally:
cursor.close()
print_table()
def set_no():
"""
sets "same" column on rows with differing value1 and value2 columns to "no"
:return: None
"""
query = '''
UPDATE db_app_testtable
SET same = 'no'
WHERE value1 != value2
'''
try:
with transaction.atomic():
cursor = connection.cursor()
cursor.execute(query)
except DatabaseError as ex:
print "set_no has error %s" % (ex)
raise
finally:
cursor.close()
print_table()
def broken_query():
"""
a function meant to break. there is no column named 'different', so this should cause
a DatabaseError to be thrown upon execution.
:return: None
"""
query = '''
UPDATE db_app_testtable
SET different = 'lol no'
WHERE value1 = value2
'''
try:
with transaction.atomic():
cursor = connection.cursor()
cursor.execute(query)
except DatabaseError as ex:
print "broken_query has error %s" % (ex)
raise
finally:
cursor.close()
...
def bulk_set():
try:
set_no()
set_yes()
broken_query()
except Exception as gen_ex:
print "Exception has occurred."
raise
如您所见,broken_query()将不起作用,这是设计的。我们正在尝试设计一个代码块,如果broken_query()失败,它将回滚set_yes()和{}所做的操作,这是不可避免的。在
鉴于django.db.transaction.atomic()的特性,这可能吗?在读取documentation时,它说,“如果代码块成功完成,更改将提交到数据库。如果出现异常,则回滚更改。“我的问题是,这是否可以扩展为使在同一代码块中调用的其他操作也回滚?在