Мое понимание состоит в том, что bulk_create()
выполняет его операцию в рамках операции , которая не совершена, если произошла ошибка. Это означает, что либо все вставки преуспели, либо none преуспел.
Например, если код генерируется, что является дубликатом тот, который уже находится в таблице, или дубликат другой в пределах партии, IntegrityError
исключение будет поднят и ни один из кодов был бы вставлен в базу данных.
С точки зрения исключений вы, скорее всего, получите подкласс 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)
Вам все равно нужно обрабатывать исключения баз данных, которые не связаны с повторяющимися значениями. Для простоты я оставил это.
Использование 'not Code.objects.filter (code = c) .exists()' вместо 'len (Codes.objects.filter (code = c)) == 0' повысит эффективность вашего кода, даже если он не отвечает на ваш вопрос. – aumo