鉴于您提供的信息,我将在 Django 中提供可能的解决方案,而无需采用原始方法。如果您可以提供更多信息,例如您正在使用的数据库以及您正在使用的约束(例如执行时间、数据完整性/一致性等),我将更新此答案
解决方案 1
假设你使用的是最新的 Django 版本,你可以使用bulk_create,并通过ignore_conflicts=True
objects = [
Model(field_1='Object Value 1'),
Model(field_1='Object Value 2'),
Model(field_1='Object Value 3'),
Model(field_1='Object Value 1'),
]
Model.objects.bulk_create(objects, ignore_conflicts=True)
注意将此参数设置为 true 的怪癖:
在支持它的数据库上(除 Oracle 之外的所有数据库),将 ignore_conflicts 参数设置为 True 会告诉数据库忽略插入任何违反约束的行(例如重复唯一值)的失败。启用此参数将禁用在每个模型实例上设置主键(如果数据库通常支持它)。
https://docs.djangoproject.com/en/dev/ref/models/querysets/#django.db.models.query.QuerySet.bulk_create
解决方案 2
或者,您可以使用 django.db.transaction.atomic 执行以下操作:
- 过滤数据库中已有的对象
- 通过删除从 1 返回的对象来修剪您的列表
-
bulk_create那些没有加入数据库的
objects_to_add = []
with transaction.atomic():
trimmed_list = filter_out_those_in_db(objects_to_add)
Model.objects.bulk_create(trimmed_list)
请注意,当事务中的代码块正在执行时,这将锁定数据库。
原子性是数据库事务的定义属性。 atomic 允许我们创建一个代码块,在其中保证数据库的原子性。如果代码块成功完成,则将更改提交到数据库。如果出现异常,则回滚更改。
https://docs.djangoproject.com/en/dev/topics/db/transactions/#django.db.transaction.atomic
解决方案 3
如果您想保持简单并且没有其他模型/表引用回此模型,您可以执行以下操作:
- 过滤记录
- 不加选择地删除所有这些记录
- 插入您的列表
这与解决方案 2 非常相似,但您可能能够在数据库中一口气完成第 1 步和第 2 步,与在 python 中进行过滤相比,减少了执行时间。
解决方案 4
如果您想更新现有记录而不只是不添加重复记录,可以使用update_or_create 更新现有记录,并创建非重复记录。
概念与get_or_create 相似,您仍然需要为每个对象执行此操作,但过滤和更新部分也可以在数据库中而不是在 python 中一举完成
一种使用给定 kwargs 更新对象的便捷方法,必要时创建一个新对象。默认值是用于更新对象的 (field, value) 对的字典。默认值中的值可以是可调用的。
https://docs.djangoproject.com/en/dev/ref/models/querysets/#update-or-create