Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get primary keys of objects created using django bulk_create

Is there a way to get the primary keys of the items you have created using the bulk_create feature in django 1.4+?

like image 928
mikec Avatar asked Apr 10 '13 18:04

mikec


3 Answers

2016

Since Django 1.10 - it's now supported (on Postgres only) here is a link to the doc.

>>> list_of_objects = Entry.objects.bulk_create([
...     Entry(headline="Django 2.0 Released"),
...     Entry(headline="Django 2.1 Announced"),
...     Entry(headline="Breaking: Django is awesome")
... ])
>>> list_of_objects[0].id
1

From the change log:

Changed in Django 1.10: Support for setting primary keys on objects created using bulk_create() when using PostgreSQL was added

like image 181
Or Duan Avatar answered Sep 24 '22 20:09

Or Duan


According to the documentation you can't do it: https://docs.djangoproject.com/en/dev/ref/models/querysets/#bulk-create

bulk-create is just for that: create a lot of objects in an efficient way saving a lot of queries. But that means that the response you get is kind of incomplete. If you do:

>>> 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]

That doesn't mean your categories doesn't have pk, just that the query didn't retrieve them (if the key is an AutoField). If you want the pks for some reason you will need to save the objects in a classic way.

like image 37
pyriku Avatar answered Sep 24 '22 20:09

pyriku


Two approaches I can think of:

a) You could do

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)

This could be a little expensive if the queryset is extremely huge.

b) If the model has a created_at field,

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)

This has the limitation of having a field that stores when the object was created.

like image 32
karthikr Avatar answered Sep 22 '22 20:09

karthikr