如何获得使用django bulk_create创build的对象的主键
有没有办法使用django 1.4+中的bulk_createfunction来获取您创build的项目的主键?
2016
Django 1.10 – 现在支持 (仅在Postgres上!)这里是一个链接到文档 。
>>> list_of_objects = Entry.objects.bulk_create([ ... Entry(headline="Django 1.0 Released"), ... Entry(headline="Django 1.1 Announced"), ... Entry(headline="Breaking: Django is awesome") ... ]) >>> list_of_objects[0].id 1
从更改日志中:
在Django 1.10中进行了更改:在使用PostgreSQL时添加了对使用bulk_create()创build的对象的主键的支持
根据文件,你不能这样做: https : //docs.djangoproject.com/en/dev/ref/models/querysets/#bulk-create
批量创build只是为了:以一种有效的方式创build大量的对象,节省了大量的查询。 但这意味着你得到的回应是不完整的。 如果你这样做:
>>> categories = Category.objects.bulk_create([ Category(titel="Python", user=user), Category(titel="Django", user=user), Category(titel="HTML5", user=user), ]) >>> [x.pk for x in categories] [None, None, None]
这并不意味着你的类别没有pk,只是查询没有检索到它们(如果键是一个AutoField
)。 如果因为某些原因需要使用pks,则需要以经典的方式保存对象。
我能想到的两种方法:
a)你可以做
category_ids = Category.objects.values_list('id', flat=True) categories = Category.objects.bulk_create([ Category(title="title1", user=user, created_at=now), Category(title="title2", user=user, created_at=now), Category(title="title3", user=user, created_at=now), ]) new_categories_ids = Category.objects.exclude(id__in=category_ids).values_list('id', flat=True)
如果查询集非常大,这可能会有点贵。
b)如果模型有一个created_at
字段,
now = datetime.datetime.now() categories = Category.objects.bulk_create([ Category(title="title1", user=user, created_at=now), Category(title="title2", user=user, created_at=now), Category(title="title3", user=user, created_at=now), ]) new_cats = Category.objects.filter(created_at >= now).values_list('id', flat=True)
这具有创build对象时存储字段的限制。
其实我的同事提出了以下这个现在看起来很明显的解决办法。 添加一个名为bulk_ref
的新列,该列填充一个唯一值并插入每一行。 之后简单地用bulk_ref
设置查询表,瞧,你的插入logging被检索。 例如:
cars = [Car( model="Ford", color="Blue", price="5000", bulk_ref=5, ),Car( model="Honda", color="Silver", price="6000", bulk_ref=5, )] Car.objects.bulk_create(cars) qs = Car.objects.filter(bulk_ref=5)
可能最简单的解决办法是手动分配主键。 这取决于具体情况,但有时从表开始使用max(id)+1就足够了,并为每个对象分配增加的数字。 但是,如果多个客户端可能同时插入logging,则可能需要一些锁。
django文档目前声明的限制:
如果模型的主键是一个AutoField,它不会像
save()
那样检索和设置主键属性。
但是,有好消息。 已经有一些关于从内存中bulk_create
的门票。 上面列出的票是最有可能有一个解决scheme,即将实施,但显然不能及时或如果它将永远做到这一点。
所以有两种可能的解决scheme,
-
等一下,看看这个补丁是否能够生产。 你可以通过testing解决scheme来帮助你,让django社区知道你的想法/问题。 https://code.djangoproject.com/attachment/ticket/19527/bulk_create_and_create_schema_django_v1.5.1.patch
-
覆盖/编写您自己的批量插入解决scheme。
这在股票Django中不起作用,但Django bug跟踪器中有一个补丁,它使bulk_create为创build的对象设置主键。
这应该工作。
categories = Category.objects.bulk_create([ Category(titel="Python", user=user), Category(titel="Django", user=user), Category(titel="HTML5", user=user), ]) >>> categories[0] [<Category: Python>] >>> categories[1] [<Category: Django>]