django 1.4+ の bulk_create 機能を使用して作成したアイテムの主キーを取得する方法はありますか?
11 に答える
2016年
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() を使用して作成されたオブジェクトに主キーを設定するためのサポートが追加されました
私が考えることができる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)
これは在庫の Django では機能しませんが、Django バグ トラッカーには、bulk_create が作成されたオブジェクトの主キーを設定するパッチがあります。
おそらく最も簡単な回避策は、主キーを手動で割り当てることです。特定のケースに依存しますが、テーブルの max(id)+1 から始めて、オブジェクトごとに増分する番号を割り当てるだけで十分な場合があります。ただし、複数のクライアントが同時にレコードを挿入する可能性がある場合は、何らかのロックが必要になる場合があります。
djangoのドキュメントには、現在、次の制限事項が記載されています。
モデルの主キーが AutoField の場合、主キー属性の取得と設定は行われ
save()
ません。
しかし、良いニュースがあります。記憶から話しているチケットがいくつかありbulk_create
ます。上記のチケットは、すぐに実装されるソリューションを持つ可能性が最も高いですが、明らかに、時間通りに、またはそれが実現するかどうかの保証はありません.
したがって、2 つの解決策が考えられます。
このパッチが製品化されるまで待ってください。記載されている解決策をテストして、django コミュニティにあなたの考えや問題を知らせることで、これを支援できます。https://code.djangoproject.com/attachment/ticket/19527/bulk_create_and_create_schema_django_v1.5.1.patch
独自の一括挿入ソリューションをオーバーライド/作成します。