2012-05-29 34 views
10

我的Django的bulk_create读了和几个“瑕疵”的:在外键中使用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? 

那么外键关系会好吗?当它说2.它不适用于多表继承场景中的子模型,这意味着任何从另一个模型继承的模型(抽象与否)都不能使用bulk_create?

回答

2

对于第一个问题,不会有这样做,因为obj将不会有其主键集,因此不能用作外键。

第二个问题,没有那不是它说的。它特别提到“多表继承”:从抽象模型继承不是多表继承。

+0

那么我将如何处理外键关系?我是否必须查询数据库以选择我刚刚插入的对象? – Derek

+0

你应该完全避免'bulk_create'在你的情况下。只需单独创建对象。 –

+7

那么你如何建议处理性能问题与个人保存? – Derek

5

尝试手动设置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,密钥不会因批量创建而增加。

+0

这是丑陋的,但它的作品! –

+0

单笔交易是否足以避免任何竞争条件?这是完全安全的吗? – kissgyorgy

+3

我已经upvoted,但我应该downvoted! id字段在数据库中不会自动增加。这是一个巨大的问题。 –