在外键中使用 Django bulk_create 对象?

Posted

技术标签:

【中文标题】在外键中使用 Django bulk_create 对象?【英文标题】:Using Django bulk_create objects in foreign keys? 【发布时间】:2012-06-03 15:42:00 【问题描述】:

我正在阅读 Django bulk_create 及其一些“缺陷”:

"
This has a number of caveats though:

1. The model's save() method will not be called, and the pre_save and post_save signals will not be sent.
2. It does not work with child models in a multi-table inheritance scenario.
3. If the model's primary key is an AutoField it does not retrieve and set the primary key attribute, as save() does.
"

我没有完全理解。因此,如果我有一个对象列表,请将其传递给 bulk_create:

objList = [a, b, c,] #none are saved
model.objects.bulk_create(objList)

我还能在外键中使用这些对象吗?

for obj in objList:
    o = otherModel(something='asdfasdf', fkey=obj)
    o.save() # will this be fine given the caveats stated above?

那么foreignKey关系会好吗?同样当它说2时。它不适用于多表继承场景中的子模型,这意味着从另一个模型(抽象或非抽象)继承的任何模型都不能使用bulk_create?

【问题讨论】:

【参考方案1】:

尝试手动设置 ID。为防止出现竞争条件,请确保将函数包装为单个事务。

from django.db import transaction, models

@transaction.commit_on_success
def bulk_create_with_manual_ids(foo_list):
    id_start = (Foo.objects.all().aggregate(models.Max('id'))['id__max'] or 0) + 1
    for i,foo in enumerate(foo_list): foo.id = id_start + i
    return Foo.objects.bulk_create(foo_list)

objList = [Foo(),Foo(),Foo()]
foo_objects = bulk_create_with_manual_ids(objList)
Bar(foo=foo_objects[0]).save()

请注意,这种方法不适用于任何具有serial 字段或其他自动递增的数据库内生成键的表。由于 Django 端正在生成 ID,因此批量创建不会增加密钥。

【讨论】:

单个事务是否足以避免任何竞争条件?它完全安全吗? 我投了赞成票,但我应该投反对票! id 字段不会在数据库中自动递增。这是个大问题。【参考方案2】:

对于第一个问题,不,您不能这样做,因为obj 没有设置其主键,因此不能用作外键。

第二个问题,不,它根本不是这么说的。其中特别提到了“多表继承”:从抽象模型继承不是多表继承。

【讨论】:

那么我将如何处理外键关系呢?我是否必须查询数据库才能选择我刚刚插入的对象? 你应该完全避免bulk_create。只需单独创建对象。 那么你建议如何处理个人保存的性能问题?

以上是关于在外键中使用 Django bulk_create 对象?的主要内容,如果未能解决你的问题,请参考以下文章

Django插入多条数据—bulk_create

如何获取使用 django bulk_create 创建的对象的主键

Django model中数据批量导入bulk_create()

Django bulk_create 忽略导致 IntegrityError 的行?

django-pyodbc bulk_create 坏了

从 django bulk_create 中选择/查询对象?