使用Django 1.8如何在单个db事务中创建多个对象并写入db?
以前的版本似乎有@commit_manually。但是当我尝试修改此代码时:https://stackoverflow.com/a/29834940我得到了一个异常
django.db.transaction.TransactionManagementError: The outermost 'atomic' block cannot use savepoint = False when autocommit is off.
在我看过很多帖子中说要用“with transaction.atomic()”块包装,但这会在每个循环中击中db。
这是我的代码的简化版本。我没有运行它,但它应该显示我正在尝试做什么。
class Foo(models.Model):
Name = models.CharField( max_length=200 )
class Bar(models.Model):
Foos = models.ManyToManyField( foo )
class Processor(object):
def run(self,):
myBar = Bar.object.create()
myList = ['a', 'b', 'c', 'd']
if True:
set_autocommit( False )
for char in myList:
myFoo = Foo.objects.create(Name=char)
myBar.Foos.add( myFoo )
commit()
set_autocommit( True )
我尝试进行所有这些更改,只打了一次db。我知道有model.objects.bulk_create,但我无法找到处理m2m关系的内容。另外bulk_create也不会返回db实例,所以我必须将它们从数据库中拉出来用于m2m关系。
答案 0 :(得分:6)
您无法在一个查询中执行所有这些操作。但是,你走在正确的轨道上。您应该使用.bulk_create()
进行批量插入,再进行一次查找以将其作为对象重新添加,以便添加到foos
。
如果您太担心后一个查询执行速度很慢,可以设置unique=True
或db_index=True
以提高效果。
您还希望使用事务维护操作的原子性,以便任何INSERT
失败,所有这些都应该回滚:
from django.db import transaction
class Foo(models.Model):
name = models.CharField(max_length=200, unique=True)
class Bar(models.Model):
foos = models.ManyToManyField(Foo)
class Processor(object):
def run(self):
transaction.set_autocommit(False)
try:
myList = ['a', 'b', 'c', 'd']
Foo.objects.bulk_create([Foo(n) for n in myList])
myBar = Bar.object.create()
myBar.foos.add(Foo.objects.filter(name__in=myList))
except:
transaction.rollback()
raise
else:
transaction.commit()
finally:
transaction.set_autocommit(True)
有关autocommit行为的详细信息,请参阅Django文档。