如何使用中间模型批量更新django M2M关系?

时间:2016-05-22 14:18:19

标签: django database orm

我有两个模型和一个中间模型(简化示例):

class Book(model.Model):
    title=models.CharField(max_length=255)
    owner=models.ManyToManyField(User, through="Ownership")

class Ownership(models.Model):
    user=models.ForeignKey(User)
    book=models.ForeignKey(Book)
    read=models.BooleanField()

现在我已经拥有了很多Book个对象,并希望将所有现有的一个对象添加到一个用户。

目前我只看到一个管理员API,它可以构建Ownership模型或将Ownership个对象(可能不保存?)添加到Book。这意味着在所有Book个对象上使用python循环,然后为每个对象构建一个Ownership对象。

是否有一个更有效的解决方案,例如Book.objects.update(owner=user, read=True),django API实际上允许这样做?

请不要介意轻微的语法问题,编写代码,因为实际代码要长很多。

2 个答案:

答案 0 :(得分:2)

您可以使用bulk_create()在一个查询中保存多个对象:

# First create an unsaved Ownership object for each book
objs = [Ownership(user=user, book=book, read=True) for book in Book.objects.all()]
# Save all ownerships in one query
Ownership.objects.bulk_create(objs)

答案 1 :(得分:1)

在没有创建Ownership对象的情况下我想不出办法,但您可以使用bulk_create将它们提交到数据库:

Ownership.objects.bulk_create(
    Ownership(read=True, user=user, book=book)
    for book in Book.objects.all())

您可以通过循环遍历图书ID来避免创建图书对象:

Ownership.objects.bulk_create(
    Ownership(read=True, user=user, book_id=book_id)
    for book_id in Book.objects.values_list('pk', flat=True))

batch_size有一个bulk_create选项,但它无助于拆分所有权对象的创建,因此如果需要创建许多对象,那么将使用大量内存。但是,我们可以将它们分开来控制记忆:

count = Book.objects.count()
batch_size = 10**5
for i in range(0, count, batch_size):
    result = Ownership.objects.bulk_create(
        Ownership(read=True, user=user, book_id=book_id)
        for book_id in Book.objects.values_list('pk', flat=True)[i:min(i + batch_size, count)])