如何使用 Django objects.bulk_create() 处理异常
How do I handle exceptions with Django objects.bulk_create()
我正在使用 bulk_create
创建模型的对象。每当抛出异常时,我该如何处理?
aList = [
Student(name="Jason"),
Student(name="Mark"),
Student(name="Tom"),
Student(name="Jason"),
Student(name="Tom"),
]
Student.objects.bulk_create(aList)
因为模型有字段 name
即 unique=True
,我必须在引发异常时处理输入。如何一一处理异常。
这没有按预期工作,
try:
# bulk_create
except:
# handlers
由于引发异常,bulk_create
进程终止。
PS。我很期待 bulk_create
。 没有 create
或 update_or_create
或 get_or_create
的循环
嗯,那是不可能的。 bulk_create
是这样定义的:
def bulk_create(self, objs, batch_size=None):
for parent in self.model._meta.get_parent_list():
if parent._meta.concrete_model is not self.model._meta.concrete_model:
raise ValueError("Can't bulk create a multi-table inherited model")
if not objs:
return objs
self._for_write = True
connection = connections[self.db]
fields = self.model._meta.concrete_fields
objs = list(objs)
self._populate_pk_values(objs)
with transaction.atomic(using=self.db, savepoint=False):
if (connection.features.can_combine_inserts_with_and_without_auto_increment_pk
and self.model._meta.has_auto_field):
self._batched_insert(objs, fields, batch_size)
else:
objs_with_pk, objs_without_pk = partition(lambda o: o.pk is None, objs)
if objs_with_pk:
self._batched_insert(objs_with_pk, fields, batch_size)
if objs_without_pk:
fields = [f for f in fields if not isinstance(f, AutoField)]
self._batched_insert(objs_without_pk, fields, batch_size)
return objs
和 _batched_insert
:
def _batched_insert(self, objs, fields, batch_size):
"""
A little helper method for bulk_insert to insert the bulk one batch
at a time. Inserts recursively a batch from the front of the bulk and
then _batched_insert() the remaining objects again.
"""
if not objs:
return
ops = connections[self.db].ops
batch_size = (batch_size or max(ops.bulk_batch_size(fields, objs), 1))
for batch in [objs[i:i + batch_size]
for i in range(0, len(objs), batch_size)]:
self.model._base_manager._insert(batch, fields=fields,
using=self.db)
因此,如您所见,bulk_create
基本上是 transaction.atomic
内的 for
循环。
还有一件事。也不可能只保存交易块内的一些条目。它要么完全执行,要么根本不执行。
实际上有一个标志 ignore_conflicts=False
,可以捕获异常,所以尝试 ModelName.objects.bulk_create([ModelName(name='spam', slug='eggs')...], ignore_conflicts=True)
是有意义的
我正在使用 bulk_create
创建模型的对象。每当抛出异常时,我该如何处理?
aList = [
Student(name="Jason"),
Student(name="Mark"),
Student(name="Tom"),
Student(name="Jason"),
Student(name="Tom"),
]
Student.objects.bulk_create(aList)
因为模型有字段 name
即 unique=True
,我必须在引发异常时处理输入。如何一一处理异常。
这没有按预期工作,
try:
# bulk_create
except:
# handlers
由于引发异常,bulk_create
进程终止。
PS。我很期待 bulk_create
。 没有 create
或 update_or_create
或 get_or_create
嗯,那是不可能的。 bulk_create
是这样定义的:
def bulk_create(self, objs, batch_size=None):
for parent in self.model._meta.get_parent_list():
if parent._meta.concrete_model is not self.model._meta.concrete_model:
raise ValueError("Can't bulk create a multi-table inherited model")
if not objs:
return objs
self._for_write = True
connection = connections[self.db]
fields = self.model._meta.concrete_fields
objs = list(objs)
self._populate_pk_values(objs)
with transaction.atomic(using=self.db, savepoint=False):
if (connection.features.can_combine_inserts_with_and_without_auto_increment_pk
and self.model._meta.has_auto_field):
self._batched_insert(objs, fields, batch_size)
else:
objs_with_pk, objs_without_pk = partition(lambda o: o.pk is None, objs)
if objs_with_pk:
self._batched_insert(objs_with_pk, fields, batch_size)
if objs_without_pk:
fields = [f for f in fields if not isinstance(f, AutoField)]
self._batched_insert(objs_without_pk, fields, batch_size)
return objs
和 _batched_insert
:
def _batched_insert(self, objs, fields, batch_size):
"""
A little helper method for bulk_insert to insert the bulk one batch
at a time. Inserts recursively a batch from the front of the bulk and
then _batched_insert() the remaining objects again.
"""
if not objs:
return
ops = connections[self.db].ops
batch_size = (batch_size or max(ops.bulk_batch_size(fields, objs), 1))
for batch in [objs[i:i + batch_size]
for i in range(0, len(objs), batch_size)]:
self.model._base_manager._insert(batch, fields=fields,
using=self.db)
因此,如您所见,bulk_create
基本上是 transaction.atomic
内的 for
循环。
还有一件事。也不可能只保存交易块内的一些条目。它要么完全执行,要么根本不执行。
实际上有一个标志 ignore_conflicts=False
,可以捕获异常,所以尝试 ModelName.objects.bulk_create([ModelName(name='spam', slug='eggs')...], ignore_conflicts=True)