206

Djangoでテーブルを更新したいのですが、生のSQLでは次のようになります。

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

私の最初の結果はこのようなものですが、それは厄介ですよね?

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

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

4

7 に答える 7

321

アップデート:

Django2.2バージョンにbulk_updateが追加されました。

古い答え:

次のdjangoドキュメントセクションを参照してください

複数のオブジェクトを一度に更新する

要するに、あなたは以下を使うことができるはずです:

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

オブジェクトを使用Fして、行のインクリメントなどを行うこともできます。

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

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

ただし、次の点に注意してください。

  • これはModelClass.saveメソッドを使用しません(したがって、内部にロジックがある場合はトリガーされません)。
  • django信号は出力されません。
  • スライスされたQuerySetに対してを実行することはできません.update()。元のQuerySetに対して実行する必要があるため、.filter()および.exclude()メソッドに依存する必要があります。
于 2012-09-30T12:43:55.860 に答える
33

ここGitHubでdjango-bulk-update見つけたものを使用することを検討してください。

インストール: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とクエリの複雑さによって異なります。このツールは、ダンプトラックというより手押し車のようなものです。

于 2015-02-16T22:42:27.510 に答える
26

Django 2.2バージョンにbulk_updateメソッドが追加されました(リリースノート)。

https://docs.djangoproject.com/en/stable/ref/models/querysets/#bulk-update

例:

# get a pk: record dictionary of existing records
updates = YourModel.objects.filter(...).in_bulk()
....
# do something with the updates dict
....
if hasattr(YourModel.objects, 'bulk_update') and updates:
    # Use the new method
    YourModel.objects.bulk_update(updates.values(), [list the fields to update], batch_size=100)
else:
    # The old & slow way
    with transaction.atomic():
        for obj in updates.values():
            obj.save(update_fields=[list the fields to update])
于 2019-01-04T08:28:05.257 に答える
13

行のコレクションに同じ値を設定する場合は、update()メソッドを任意のクエリ用語と組み合わせて使用​​して、1つのクエリのすべての行を更新できます。

some_list = ModelClass.objects.filter(some condition).values('id')
ModelClass.objects.filter(pk__in=some_list).update(foo=bar)

条件に応じて異なる値で行のコレクションを更新する場合は、最良の場合、値に従って更新をバッチ処理できます。列をX値の1つに設定する1000行があるとすると、事前にバッチを準備してから、X個の更新クエリ(それぞれが基本的に上記の最初の例の形式を持つ)+最初のSELECTのみを実行できます。 -クエリ。

すべての行に一意の値が必要な場合、更新ごとに1つのクエリを回避する方法はありません。後者の場合にパフォーマンスが必要な場合は、おそらくCQRS/イベントソーシングなどの他のアーキテクチャを調べてください。

于 2018-11-15T14:05:38.087 に答える
3

上記の質問に関してインターネットで見つけた便利なコンテンツは次のとおりです。

https://www.sankalpjonna.com/learn-django/running-a-bulk-update-with-django

非効率的な方法

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

効率的な方法

ModelClass.objects.filter(name = 'bar').update(name="foo") # for single value 'foo' or add loop

Bulk_updateを使用する

update_list = []
model_qs= ModelClass.objects.filter(name = 'bar')
for obj in model_qs:
    model_obj =ModelClass.object.get(id=obj.id)
    model_obj.name = "foo" # Or what ever the value is for simplicty im providing foo only
    update_list.append(model_obj)
    
ModelClass.objects.bulk_update(update_list,['name'])

アトミックトランザクションの使用

from django.db import transaction

with transaction.atomic():
    model_qs = ModelClass.objects.filter(name = 'bar')
    for obj in model_qs:
       ModelClass.objects.filter(name = 'bar').update(name="foo")

賛成票はありますか?よろしくお願いします:ご清聴ありがとうございました;)

于 2021-11-07T22:12:24.767 に答える
2

同じ値で更新するには、これを使用するだけです

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

異なる値で更新するには

list = ModelClass.objects.filter(name = 'bar')
obj_to_be_update = []
for obj in list:
    obj.name = "Dear "+obj.name
    obj_to_be_update.append(obj)
ModelClass.objects.bulk_update(obj_update_list, ['name'], batch_size=1000)

毎回保存シグナルをトリガーするのではなく、更新するすべてのオブジェクトをリストに保持し、更新シグナルを一度にトリガーします。

于 2022-01-19T04:29:25.833 に答える
1

ITは、テーブルで更新されたオブジェクトの数を返します。

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

一括更新と作成の詳細については、このリンクを参照してください。 一括更新と作成

于 2020-06-22T06:00:51.247 に答える