我需要创建许多独特的代码并将其插入数据库中。
当然我可以这样写:
codes = set()
while len(codes) < codes_size:
c = generate_code()
if len(Codes.objects.filter(code=c)) == 0:
codes.add(Codes(c))
Codes.objects.bulk_create(codes)
但是当数据库已经包含很多代码时,它的工作速度很慢。
如果在每一代之后插入代码 - 它也非常慢。
现在最好的想法 - 在bulk_create
之前不验证代码。如果bulk_create
引发异常,则再次重新生成所有代码。例外情况非常罕见,但是当数据库更大时,异常会更频繁。
bulk_create
不说哪个代码会引发异常。
答案 0 :(得分:1)
我的理解是bulk_create()
在事务中执行它的操作,如果发生错误,它不会被提交。这意味着所有插入成功,或 none 成功。
例如,如果生成的代码与表中已有的代码重复,或者批处理中的另一个代码重复,则会引发IntegrityError
异常且 none 的代码将被插入到数据库中。
就例外情况而言,您可能会获得django.db.utils.DatabaseError
的子类,例如django.db.utils.IntegrityError
。因为您不知道将引发哪个数据库错误,所以您应该捕获DatabaseError
。
我认为没有任何方法可以从异常中了解哪些代码导致了问题。
处理此问题的一种方法是预先生成所有代码,然后在transaction内使用filter()
测试它们是否已经一次存在于表中并在那里插入它们没有重复:
from django.db import transaction
codes = set()
while len(codes) < codes_size:
codes.add(generate_code())
with transaction.atomic():
# check for any duplicate codes in table...
dups = Codes.objects.filter(code__in=codes)
if len(dups):
print 'Duplicate code(s) generated: {}'.format(dup.code for dup in dups)
# remove dups from codes, and generate additional codes to make up the shortfall.
# Note that this might also result in duplicates....
else:
Codes.objects.bulk_create(Codes(code) for code in codes)
您仍然需要处理不是由于重复值而导致的数据库异常。为简单起见,我把它遗漏了。