You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django中如何实现支持唯一性校验的bulk_create批量数据插入

Django批量插入唯一对象的高性能方案

要实现单次数据库请求完成唯一对象批量入库,同时保证不产生重复数据,只需结合数据库唯一约束和bulk_create的冲突处理参数即可,性能远高于循环调用get_or_create。

步骤1:给模型添加数据库层面的唯一约束

首先需要在模型中定义和get_or_create校验逻辑一致的唯一约束,让数据库可以识别重复条目:

# models.py
from django.db import models

class Person(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)

    class Meta:
        # 定义first_name和last_name联合唯一,和原get_or_create的校验规则保持一致
        constraints = [
            models.UniqueConstraint(fields=['first_name', 'last_name'], name='unique_full_name')
        ]

添加约束后需要执行makemigrations和migrate命令,让约束在数据库中生效。

步骤2:调用bulk_create时开启冲突处理

Django 2.2及以上版本的bulk_create支持ignore_conflicts参数,开启后插入时遇到唯一约束冲突的条目会自动跳过,不会报错也不会产生重复数据,全程仅执行1次数据库请求:

# 准备批量插入的数据集,即使内部存在重复也不需要提前处理
person_list = [
    Person(first_name='Leon', last_name='Mariano'),
    Person(first_name='Leon', last_name='Mariano'),
    Person(first_name='Bob', last_name='Smith'),
]

# 单次请求完成插入,冲突条目自动忽略
Person.objects.bulk_create(person_list, ignore_conflicts=True)

扩展场景

如果你遇到重复条目时需要更新已有数据而非跳过,可以使用Django 4.1及以上版本支持的update_conflicts参数:

# 示例:假设Person模型新增age字段,姓名重复时更新age字段
person_list = [
    Person(first_name='Leon', last_name='Mariano', age=30),
    Person(first_name='Bob', last_name='Smith', age=25),
]

Person.objects.bulk_create(
    person_list,
    update_conflicts=True,
    unique_fields=['first_name', 'last_name'], # 指定判断冲突的唯一字段
    fields=['age'] # 冲突时需要更新的字段
)

低版本Django兼容方案

如果使用的Django版本不支持ignore_conflicts参数,可以用2次数据库请求实现同等效果,性能仍远高于循环get_or_create:

  • 先对要插入的数据集做内存去重
  • 查询数据库中已存在的条目,过滤掉重复数据
  • 把剩下的新数据批量插入

内容的提问来源于stack exchange,提问作者CbrRRider

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 16:15:06