pilih dan perbarui catatan basis data dengan satu queryset

139

Bagaimana cara menjalankan updatedan selectpernyataan yang sama querysetdaripada harus melakukan dua pertanyaan: - satu untuk memilih objek - dan satu untuk memperbarui objek

Setara dengan SQL akan menjadi seperti:

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

Jawaban:

267

Gunakan metode objekupdate queryset :

MyModel.objects.filter(pk=some_value).update(field1='some value')
Daniel Roseman
sumber
95
Hanya peringatan yang adil ... jika Anda menggunakan updatemetode seperti ini maka sinyal apa pun yang melekat pada model itu atau "hal kode" lainnya tidak akan berjalan melawan objek. Hanya sebuah petunjuk dari seseorang yang terbakar :)
DMac the Destroyer
@DMactheDestroyer Bung terima kasih atas info berharga itu. Maka haruskah kita menggunakan cara yang lebih lama untuk memperbaruinya? (Yaitu) dapatkan dan simpan?
@learning Bung, semuanya tergantung pada skenario Anda. The updateMetode sangat bagus untuk update massa, tetapi harus berangkat peringatan di kepala Anda ketika Anda menggunakannya bahwa Anda perlu untuk meninjau sinyal yang melekat bahwa objek yang juga mungkin perlu secara manual dipecat
DMAC Destroyer
3
Apakah mungkin untuk mengakses instance model saat ini dalam fungsi pembaruan? likeMyModel.objects.filter(pk=some_value).update(field1=self.data)
Dipak
8
@DipakChandranP Anda harus mengajukan pertanyaan baru alih-alih mengomentari yang berumur enam tahun. Tapi ekspresi F () mungkin Anda inginkan.
Daniel Roseman
70

Objek basis data Django menggunakan metode save () yang sama untuk membuat dan mengubah objek.

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

Bagaimana Django mengetahui UPDATE vs INSERT
Jika atribut primary key objek diatur ke nilai yang mengevaluasi True (yaitu, nilai selain None atau string kosong), Django mengeksekusi UPDATE. Jika atribut kunci utama objek tidak disetel atau jika UPDATE tidak memperbarui apa pun, Django mengeksekusi INSERT.

Ref .: https://docs.djangoproject.com/en/1.9/ref/models/inances/

Slipstream
sumber
17

Jawaban ini membandingkan dua pendekatan di atas. Jika Anda ingin memperbarui banyak objek dalam satu baris, pilih:

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

Jika tidak, Anda harus mengulangi set kueri dan memperbarui objek individual:

#Approach 2    
objects = MyModel.objects.filter(field1='Computer')
for obj in objects:
    obj.field2 = 'cool'
    obj.save()
  1. Pendekatan 1 lebih cepat karena, ia hanya membuat satu permintaan basis data, dibandingkan dengan pendekatan 2 yang membuat permintaan basis data 'n +1'. (Untuk n item dalam set kueri)

  2. Pendekatan fist membuat satu permintaan db yaitu UPDATE, yang kedua membuat dua: SELECT dan kemudian UPDATE.

  3. Imbalannya adalah, misalkan Anda memiliki pemicu, seperti memperbarui updated_onatau bidang terkait seperti itu, itu tidak akan dipicu pada pembaruan langsung yaitu pendekatan 1.

  4. Pendekatan 1 digunakan pada queryset, sehingga dimungkinkan untuk memperbarui beberapa objek sekaligus, tidak dalam hal pendekatan 2.

Pransh Tiwari
sumber
Mengenai 1. - Saya pikir hasil permintaan akan di-cache pada panggilan pertama ke permintaan, maka sebenarnya masih ada hanya satu panggilan ke DB.
user2340939
2

hanya dalam serializerhal ini, Anda dapat memperbarui dengan cara yang sangat sederhana!

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

    my_model_serializer.save()

hanya dalam hal dalam formhal!

instance = get_object_or_404(MyModel, id=id)
form = MyForm(request.POST or None, instance=instance)
if form.is_valid():
    form.save()
Jamil Noyda
sumber
Saya pikir serializers berasal dari Djanog Rest Framework dan tidak sesuai Django.
Code-Apprentice
1
Ya, bagaimanapun Django formdari Django Proper.
Jamil Noyda