在Django 1.8中创建多个没有多次匹配到db的对象

bri*_*ian 10 database django transactions atomicity

使用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.
Run Code Online (Sandbox Code Playgroud)

在我看过很多帖子中说要用"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 )
Run Code Online (Sandbox Code Playgroud)

我正在尝试进行所有这些更改,只打了一次db.我知道有model.objects.bulk_create,但我找不到处理m2m关系的方法.另外bulk_create不会返回db实例,因此我必须将它们从m2中拉出来以获取m2m关系.

ozg*_*gur 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)
Run Code Online (Sandbox Code Playgroud)

有关自动提交行为的更多信息,请参阅Django文档.