単一のクエリセットでデータベースレコードを選択して更新する


139

2つのクエリを実行するのではなく、同じようにupdateand selectステートメントを実行するにはどうすればよいですかqueryset。1つはオブジェクトを選択するためのもので、もう1つはオブジェクトを更新するためのものです。

SQLでこれに相当するものは次のようになります。

update my_table set field_1 = 'some value' where pk_field = some_value

回答:


267

queryset オブジェクトupdateメソッドを使用します

MyModel.objects.filter(pk=some_value).update(field1='some value')

95
公正な警告です... updateこのような方法を使用すると、そのモデルまたは他の「コード」に関連付けられている信号はオブジェクトに対して実行されません。火傷した人からのポインタ:)
DMac the Destroyer 2012

@DMactheDestroyer貴重な情報をありがとう。それでは、古い方法で更新する必要がありますか?(つまり)取得して保存しますか?

@まあまあ学習、それはすべてあなたのシナリオに依存します。このupdateメソッドは大量更新には最適ですが、使用すると、手動で起動する必要がある可能性のある、そのオブジェクトに接続されている信号を確認する必要があるという警告が
頭に浮かぶはずです

3
更新機能で現在のモデルインスタンスにアクセスできますか?のようなものMyModel.objects.filter(pk=some_value).update(field1=self.data)
-Dipak

8
@DipakChandranP 6歳の質問にコメントするのではなく、新しい質問をする必要があります。しかし、F()式はおそらく望んでいるでしょう。
Daniel Roseman

70

Djangoデータベースオブジェクトは、オブジェクトの作成と変更に同じsave()メソッドを使用します。

obj = Product.objects.get(pk=pk)
obj.name = "some_new_value"
obj.save()

DjangoがUPDATEとINSERTを認識する方法
オブジェクトの主キー属性がTrueと評価される値(つまり、Noneまたは空の文字列以外の値)に設定されている場合、DjangoはUPDATEを実行します。オブジェクトの主キー属性が設定されていない場合、またはUPDATEが何も更新しなかった場合、DjangoはINSERTを実行します。

参照:https : //docs.djangoproject.com/en/1.9/ref/models/instances/


17

この回答は、上記の2つのアプローチを比較しています。1行で多くのオブジェクトを更新する場合は、次のようにします。

# Approach 1
MyModel.objects.filter(field1='Computer').update(field2='cool')

それ以外の場合は、クエリセットを反復処理して個々のオブジェクトを更新する必要があります。

#Approach 2    
objects = MyModel.objects.filter(field1='Computer')
for obj in objects:
    obj.field2 = 'cool'
    obj.save()
  1. アプローチ1は、「n + 1」データベースクエリを作成するアプローチ2と比較して、データベースクエリを1つだけ作成するため、より高速です。(クエリセットのnアイテムの場合)

  2. 最初のアプローチは1つのdbクエリ、つまりUPDATEを作成し、2番目のアプローチはSELECTとUPDATEの2つを作成します。

  3. トレードオフは、更新updated_onやそのような関連フィールドなどのトリガーがある場合、直接更新、つまりアプローチ1ではトリガーされないことです。

  4. アプローチ1はクエリセットで使用されるため、アプローチ2の場合ではなく、一度に複数のオブジェクトを更新できます。


1.について-クエリの結果はクエリの最初の呼び出しでキャッシュされるため、実際にはまだDBへの呼び出しが1つしかありません。
user2340939

2

ある場合にのみ、serializer非常に簡単な方法で更新できます!

my_model_serializer = MyModelSerializer(
    instance=my_model, data=validated_data)
if my_model_serializer.is_valid():

    my_model_serializer.save()

form物事の場合にのみ!

instance = get_object_or_404(MyModel, id=id)
form = MyForm(request.POST or None, instance=instance)
if form.is_valid():
    form.save()

シリアライザはDjanog Rest Frameworkからのものであり、Django固有のものではないと思います。
コード見習い

1
ええ、しかしDjango form、ジャンゴプロパーからです。
Jamil Noyda
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.