Django 中的批量更新

Vaibhav Vaibhav 2023年1月30日
  1. bulk_update() Django 中的方法
  2. bulk_update() 方法的缺点
Django 中的批量更新

在 Django 中,默认情况下,每个模型都有一个对象管理器。这个管理器可以做很多事情,比如获取模型实例、过滤模型实例、删除模型实例。我们甚至可以通过继承 Django 提供的基础管理器来创建我们自己的管理器。

现在,我们应用的每个查询,例如使用 get() 函数检索单个模型实例或使用 filter() 方法过滤实例,都会命中数据库一次。这意味着,如果我们有如下 5 个 get() 语句,数据库将被单独查询 5 次。

person = Person.objects.get(id=1)
person = Person.objects.get(id=2)
person = Person.objects.get(id=3)
person = Person.objects.get(id=4)
person = Person.objects.get(id=5)

这是一种低效的方法,因为我们正在为单个任务单独访问数据库。如果我们必须为某些模型查询多个实例或更新多个实例,这种方法会显着降低我们的应用程序的速度。

为了解决这个问题,Django 有一个内置函数,通常可以用于在一个查询中更新多个实例。

bulk_update() Django 中的方法

bulk_update 方法具有三个参数,即 objsfieldsbatch_size

  1. objs - 要执行的操作列表
  2. fields - 必须执行查询的字段列表
  3. batch_size - 要在单个数据库查询中保存的对象数。它是一个可选参数。默认情况下,更新并保存所有对象。

考虑一个例子。假设我们有一个 Person 模型,我们必须使用 bulk_update() 方法将所有人员的年龄增加 1。我们会做以下事情。

models.py 中:

from django.db import models


class Person(models.Model):
    username = models.CharField(max_length=200, unique=True)
    firstName = models.CharField(max_length=200)
    middleName = models.CharField(max_length=200)
    lastName = models.CharField(max_length=200)
    age = models.IntegerField(default=0)

views.py 中:

people = Person.objects.all()

for person in people:
    person.age += 1

Person.objects.bulk_update(people, update_fields=["age"])

此操作将在单个查询中更新所有人员的年龄,这是非常有效的。

bulk_update() 方法的缺点

bulk_update() 方法非常好,但并非所有的闪光点都是金子。这种方法有一些缺点。

  • 使用 bulk_update() 方法,我们无法更新实例的主键。
  • 每个模型都有一个 save() 方法。使用 bulk_update() 方法时不会调用此方法。
  • 如果我们要为大量记录更新许多列,则必须提及批量大小。否则,生成的 SQL 查询会很长。
作者: Vaibhav Vaibhav
Vaibhav Vaibhav avatar Vaibhav Vaibhav avatar

Vaibhav is an artificial intelligence and cloud computing stan. He likes to build end-to-end full-stack web and mobile applications. Besides computer science and technology, he loves playing cricket and badminton, going on bike rides, and doodling.