2012-09-30 29 views
83

私はジャンゴでテーブルを更新したい - 生のSQLでこのような何か:Djangoで '一括更新'するには?

update tbl_name set name = 'foo' where name = 'bar' 

私の最初の結果は、このようなものである - しかし、それは厄介だ、そうではありませんか?

list = ModelClass.objects.filter(name = 'bar') 
for obj in list: 
    obj.name = 'foo' 
    obj.save() 

もっとエレガントな方法がありますか?

+1

バッチインサートを探している可能性があります。 http://stackoverflow.com/questions/4294088/accelerate-bulk-insert-using-djangos-orm – Pramod

+0

新しいデータを挿入するのは好きではありません - 既存のものを更新するだけです。 – Thomas

+2

多分select_for_updateの助けを借りて? https://docs.djangoproject.com/en/dev/ref/models/querysets/#django.db.models.query.QuerySet.select_for_update –

答えて

149

djangoドキュメントのupdate機能を参照してください:https://docs.djangoproject.com/en/dev/ref/models/querysets/#update

あなたが使用することができるはず要するに

ModelClass.objects.filter(name='bar').update(name="foo") 

ます。また、行をインクリメントするようなことを行うためにFオブジェクトを使用することができます。しかしhttps://docs.djangoproject.com/en/1.9/topics/db/queries/

from django.db.models import F 
Entry.objects.all().update(n_pingbacks=F('n_pingbacks') + 1) 

は、マニュアルを参照してください、注:

  • これはModelClass.saveメソッドを使用しません(内部にロジックがある場合、トリガーされません)。
  • djangoシグナルが送出されません。
+21

'save()'、 'DateTimeField'フィールドを'auto_now = True'(変更された列)は更新されません。 – Arthur

+2

しかし、 'ModelClass.objects.filter(name = 'bar')。update(name =" foo ")は一括更新の目的を果たさない、異なるIDのデータが異なる場合、 ? – Shashank

+0

@shihon私はあなたが正しいかどうかはわかりませんが、答えに例を追加しました。 –

24

django-bulk-updateが見つかりました。here on GitHubです。

インストール:pip install django-bulk-update

を実装します(コードは、プロジェクトのREADMEファイルから直接取得)

from bulk_update.helper import bulk_update 

random_names = ['Walter', 'The Dude', 'Donny', 'Jesus'] 
people = Person.objects.all() 

for person in people: 
    r = random.randrange(4) 
    person.name = random_names[r] 

bulk_update(people) # updates all columns using the default db 

更新:をマルクがコメントで指摘するように、これはで数千行を更新するには適していません一度。小規模なバッチ10〜100に適していますが、適切なバッチのサイズは、CPUとクエリの複雑さによって異なります。このツールは、ダンプトラックよりも車輪のようなものです。

+5

私はdjango-bulk-updateを試しましたが、私は個人的にそれを使用することをお勧めしません。内部的には、次のような単一のSQL文を作成します。UPDATE "table" SET "field" = CASE "id" WHEN%s THEN%s WHEN%s THEN%s [...] %s、%s、[...]);これはいくつかの行(バルクアップデーターが不要な場合)のようなものですが、10,000の場合、クエリは非常に複雑で、ディスクへの書き込み時間よりもクエリを理解するのに100%の時間が費やされます。 –

+0

@MarcGarcia良い点。 – Dejell

+2

@MarcGarcia一括更新は価値がなく、何千もの更新が必要な場合にのみ必要であるとは私は同意しません。一度に10,000行を使用することは、あなたが言及した理由ではお勧めできませんが、50行を一度に更新することは、50個の別々の更新要求でデータベースを起動するよりはるかに効率的です。 –