首页 > 解决方案 > 如何在 Django 的一个查询中保存所有模型更改

问题描述

我尝试修改某些模型(如User模型)的许多实例,并且这种更改是不同的(我不想使用更新QuerySet方法并且不适用于我的场景)。

例如,有些用户需要更改first_name,有些用户需要更改last_name并获得以下用户:all_user = User.objects.all()

我想如果我在更改后对每个实例使用保存方法,Django 会发送一个查询来保存它!

如何在一个查询中保存对数据库的所有更改,而不是在模型上使用 foreach 并一一保存?

标签: python-3.xdjangodjango-models

解决方案


鉴于@iklinac 的评论,我会彻底推荐实施 django 自己的批量更新方法,这里详细介绍

这与我在下面的原始答案非常相似,但看起来该功能现在已内置。

# bulk_update(objs, fields, batch_size=None)
>>> objs = [
...    Entry.objects.create(headline='Entry 1'),
...    Entry.objects.create(headline='Entry 2'),
... ]
>>> objs[0].headline = 'This is entry 1'
>>> objs[1].headline = 'This is entry 2'
>>> Entry.objects.bulk_update(objs, ['headline'])

原始答案

有一个名为django-bulk-update的包,它类似于 django 内置的 bulk create。

我使用它的一个例子是管理类中操作的一部分;

@admin.register(Token)
class TokenAdmin(admin.ModelAdmin):
    list_display = (
        'id',
        'type'
    )

    actions = (
        'set_type_charity',
    )

    def set_type_charity(self, request, queryset):
        for token in queryset:
            token.type = Token.Type.CHARITY

        bulk_update(
            queryset,
            update_fields=['type', 'modified'],
            batch_size=1000
        )

用法,取自他们的自述文件;

与经理:

import random
from django_bulk_update.manager import BulkUpdateManager
from tests.models import Person

class Person(models.Model):
    ...
    objects = BulkUpdateManager()

random_names = ['Walter', 'The Dude', 'Donny', 'Jesus']
people = Person.objects.all()
for person in people:
  person.name = random.choice(random_names)

Person.objects.bulk_update(people, update_fields=['name'])  # updates only name column
Person.objects.bulk_update(people, exclude_fields=['username'])  # updates all columns except username
Person.objects.bulk_update(people)  # updates all columns
Person.objects.bulk_update(people, batch_size=50000)  # updates all columns by 50000 sized chunks

有帮手:

import random
from django_bulk_update.helper import bulk_update
from tests.models import Person

random_names = ['Walter', 'The Dude', 'Donny', 'Jesus']
people = Person.objects.all()
for person in people:
  person.name = random.choice(random_names)

bulk_update(people, update_fields=['name'])  # updates only name column
bulk_update(people, exclude_fields=['username'])  # updates all columns except username
bulk_update(people, using='someotherdb')  # updates all columns using the given db
bulk_update(people)  # updates all columns using the default db
bulk_update(people, batch_size=50000)  # updates all columns by 50000 sized chunks using the default db

推荐阅读