Django 1.4+のbulk_create機能を使用して作成したアイテムの主キーを取得する方法はありますか?
Django 1.10-)がサポートされた(Postgresのみ) ドキュメントへのリンク 。
>>> 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
変更ログから:
変更されたDjango 1.10:PostgreSQLの使用時にbulk_create()を使用して作成されたオブジェクトに主キーを設定するサポートが追加されました
ドキュメントによると、あなたはそれを行うことができません: https://docs.djangoproject.com/en/dev/ref/models/querysets/#bulk-create
bulk-createはそのためだけのものです。多くのクエリを保存する効率的な方法で多くのオブジェクトを作成します。しかし、それはあなたが得る応答が一種の不完全であることを意味します。もしあなたがそうするなら:
>>> 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が必要な場合は、古典的な方法でオブジェクトを保存する必要があります。
私が考えることができる2つのアプローチ:
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)
これには、オブジェクトが作成されたときに保存するフィールドを持つという制限があります。
実際、私の同僚は次の解決策を提案しましたが、それは今ではとても明白です。 bulk_ref
という新しい列を追加します。この列には一意の値を入力し、すべての行に挿入します。その後、事前にbulk_ref
を設定してテーブルにクエリを実行するだけで、挿入されたレコードが取得されます。例えば。:
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で開始し、すべてのオブジェクトに増分する番号を割り当てるだけで十分な場合があります。ただし、複数のクライアントが同時にレコードを挿入する場合、何らかのロックが必要になる場合があります。
これは標準のDjangoでは機能しませんが、 Djangoバグトラッカー)のパッチ があり、bulk_createが作成されたオブジェクトの主キーを設定します。
Django documentation は現在、制限の下で述べています:
モデルの主キーがAutoFieldである場合、
save()
のように主キー属性を取得および設定しません。
しかし、良いニュースがあります。メモリからbulk_create
について話すチケットがいくつかありました。 上記のチケット は、すぐに実装されるソリューションを持っている可能性が最も高いですが、明らかに、時間に関する保証はありません。
したがって、2つの解決策があります。
このパッチが実稼働するかどうかを確認してください。上記の解決策をテストして、Djangoコミュニティにあなたの考えや問題を知らせてください。 https://code.djangoproject.com/attachment/ticket/19527 /bulk_create_and_create_schema_Django_v1.5.1.patch
独自の一括挿入ソリューションをオーバーライド/作成します。