web-dev-qa-db-ja.com

Django(SQL、Python、Django)でget_or_create()を使用して一括挿入する効率的な方法

これを行うためのより効率的な方法はありますか?

for item in item_list:
    e, new = Entry.objects.get_or_create(
        field1 = item.field1,
        field2 = item.field2,
    )
23
kemar

Get_or_create(またはcreate)を使用して適切な一括挿入を行うことはできず、これを簡単に行うためのAPIはありません。

テーブルが単純で、生のSQLを使用して行を作成するのがそれほど面倒ではない場合、それほど難しくはありません。何かのようなもの:

INSERT INTO site_entry (field1, field2)
(
         SELECT i.field1, i.field2
         FROM (VALUES %s) AS i(field1, field2)
         LEFT JOIN site_entry as existing
                 ON (existing.field1 = i.field1 AND existing.field2 = i.field2)
         WHERE existing.id IS NULL
)

ここで、%sは("field1, field2"), ("field3, field4"), ("field5, field6")のような文字列であり、自分で適切に作成してエスケープする必要があります。

11
Glenn Maynard

何を目指しているかによります。 manage.pyの-​​ loaddata 関数を使用して、適切な形式(JSON、XML、YAMLなど)でデータをロードできます。

このディスカッション も参照してください。

4
Felix Kling

1.4以降、bulk_createを実行できます

ドキュメント を参照してください

*ただし、注意事項に注意してください(最も重要なのは、モデルのsave()メソッドが呼び出されないため、pre_saveおよびpost_saveシグナルが送信されないことです)。*

1
Gumbah

ないでしょう。

しかし、属性としてfield1field2がある場合、itemsはどのタイプか疑問に思います。エントリを表す別のクラスが存在するようですが、models.Modelから派生していません。たぶん、このクラスを省略して、それらのアイテムを作成する代わりに、すぐにEntryインスタンスを作成することができます。

0
Johannes Charra

item_listにあるものがDBにすでに存在するかどうかわからず、モデルオブジェクトが必要な場合は、get_or_createが間違いなく最適な方法です。

アイテムがDBにないことがわかっている場合は、次のことを行う方がはるかに良いでしょう。

for item in item_list:
    new = Entry.objects.create(
        field1 = item.field1,
        field2 = item.field2,
    )

また、オブジェクトが必要ない場合は、関数呼び出しからの戻りを無視してください。 DBの処理速度は向上しませんが、それが問題になる場合はメモリ管理に役立ちます。

データがすでにDBにあるかどうかわからないが、どちらかのフィールドにunique=Trueフラグが付いている場合、DBは一意性を強制し、例外をキャッチして先に進むことができます。これにより、既存のオブジェクトを選択する試みが回避され、余分なDBヒットが防止されます。

from Django.db import IntegrityError

for item in item_list:
    try:
        new = Entry.objects.create(
            field1 = item.field1,
            field2 = item.field2,
        )
    except IntegrityError:
        continue

どちらの場合も、トランザクションを手動で管理することで速度を上げることができます。 Djangoは、保存ごとにトランザクションを自動的に作成してコミットしますが、特定の関数で大量のDB保存を行うことがわかっている場合は、効率を大幅に向上させるデコレータを提供します。= Djangoドキュメントは、私がここでできるよりもこれらすべてを説明するのに優れていますが、おそらく特に注意を払う必要があります Django.db.transaction.commit_on_success

0
Paul McLanahan