【问题标题】:How do I handle exceptions with Django objects.bulk_create()如何使用 Django objects.bulk_create() 处理异常
【发布时间】:2016-08-09 00:59:38
【问题描述】:

我正在使用bulk_create创建模型对象。每当引发异常时,我该如何处理?

aList = [
    Student(name="Jason"),
    Student(name="Mark"),
    Student(name="Tom"),
    Student(name="Jason"),
    Student(name="Tom"),
]

Student.objects.bulk_create(aList)

由于模型具有字段 nameunique=True,因此我必须在引发异常时处理输入。如何一一处理异常。

这不按预期工作,

try:
    # bulk_create
except:
    # handlers

引发异常时,bulk_create 进程将终止。

PS。我期待着bulk_createcreateupdate_or_createget_or_create 没有循环

【问题讨论】:

标签: python django django-models django-orm


【解决方案1】:

实际上有一个标志ignore_conflicts=False,可以捕获异常,所以尝试ModelName.objects.bulk_create([ModelName(name='spam', slug='eggs')...], ignore_conflicts=True)是有意义的

【讨论】:

    【解决方案2】:

    嗯,这是不可能的。这就是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 循环。

    还有一件事。在事务块内只保存一些条目也是不可能的。它要么完全执行,要么根本不执行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-10-25
      • 1970-01-01
      • 2017-10-16
      • 2010-10-16
      • 2012-08-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多