Sinyal Django vs. metode penyimpanan utama

89

Saya mengalami masalah saat memikirkan hal ini. Saat ini saya memiliki beberapa model yang terlihat seperti ini:

 def Review(models.Model)
    ...fields...
    overall_score = models.FloatField(blank=True)

def Score(models.Model)
    review = models.ForeignKey(Review)
    question = models.TextField()
    grade = models.IntegerField()

Ulasan memiliki beberapa "skor", overall_score adalah rata-rata skor. Saat ulasan atau skor disimpan, saya perlu menghitung ulang rata-rata overall_score. Saat ini saya menggunakan metode penyimpanan yang diganti. Akankah ada keuntungan menggunakan operator sinyal Django?

imjoevasquez.dll
sumber

Jawaban:

85

Sinyal simpan / hapus umumnya menguntungkan dalam situasi di mana Anda perlu membuat perubahan yang tidak sepenuhnya spesifik untuk model yang dimaksud, atau dapat diterapkan pada model yang memiliki kesamaan, atau dapat dikonfigurasi untuk digunakan di berbagai model.

Satu tugas umum dalam savemetode yang diganti adalah pembuatan siput otomatis dari beberapa bidang teks dalam model. Itu adalah contoh dari sesuatu yang, jika Anda perlu mengimplementasikannya untuk sejumlah model, akan mendapat manfaat dari penggunaan pre_savesinyal, di mana penangan sinyal dapat mengambil nama bidang siput dan nama bidang untuk menghasilkan siput. Setelah Anda memiliki sesuatu seperti itu, semua fungsionalitas yang ditingkatkan yang Anda tempatkan juga akan berlaku untuk semua model - misalnya mencari siput yang akan Anda tambahkan untuk jenis model yang dimaksud, untuk memastikan keunikan.

Aplikasi yang dapat digunakan kembali sering kali mendapat manfaat dari penggunaan sinyal - jika fungsionalitas yang mereka sediakan dapat diterapkan ke model apa pun, mereka umumnya (kecuali jika tidak dapat dihindari) tidak ingin pengguna harus langsung memodifikasi model mereka untuk mendapatkan manfaat darinya.

Dengan django-mptt , misalnya, saya menggunakan pre_savesinyal untuk mengelola sekumpulan bidang yang menjelaskan struktur pohon untuk model yang akan dibuat atau diperbarui dan pre_deletesinyal untuk menghapus detail struktur pohon untuk objek yang dihapus dan keseluruhannya. sub-pohon objek sebelumnya dan mereka akan dihapus. Karena penggunaan sinyal, pengguna tidak perlu menambah atau memodifikasi saveatau deletemetode pada model mereka untuk melakukan manajemen ini untuk mereka, mereka hanya perlu membiarkan django-mptt mengetahui model mana yang mereka inginkan untuk dikelola.

Jonny Buchanan
sumber
Bagaimana jika penangan sinyal memicu pengecualian? Saya kira mereka seharusnya tidak memicu pengecualian, atau mereka tidak cocok. Apakah aku salah?
x-yuri
20

Kamu bertanya:

Akankah ada keuntungan menggunakan operator sinyal Django?

Saya menemukan ini di dokumen django:

Metode model yang diganti tidak dipanggil pada operasi massal

Perhatikan bahwa metode delete () untuk sebuah objek tidak perlu dipanggil saat menghapus objek secara massal menggunakan QuerySet atau sebagai hasil dari penghapusan berjenjang. Untuk memastikan logika delete yang disesuaikan dijalankan, Anda dapat menggunakan sinyal pre_delete dan / atau post_delete.

Sayangnya, tidak ada solusi saat membuat atau memperbarui objek secara massal, karena tidak ada save (), pre_save, dan post_save yang dipanggil.

Dari: Mengganti metode model yang telah ditentukan sebelumnya

guettli
sumber
3
Tampilan daftar admin Django menggunakan hapus massal ... bingung sampai menemukan berita gembira ini.
N.Balauro
8
itu juga mengatakan "Sayangnya, tidak ada solusi saat membuat atau memperbarui objek secara massal, karena tidak ada save (), pre_save, dan post_save yang dipanggil." - jadi saya tidak berpikir ini adalah pertukaran antara metode ini.
Cory
Ini berlaku untuk kedua metode, jadi jawabannya adalah: "tidak, tidak ada manfaat menggunakan sinyal sebagai lawan menimpa savemetode"?
Flimm
3

Jika Anda menggunakan sinyal, Anda dapat memperbarui Skor ulasan setiap kali model skor terkait disimpan. Tetapi jika tidak membutuhkan fungsionalitas seperti itu, saya tidak melihat alasan untuk memasukkan ini ke dalam sinyal, itu hal-hal yang berhubungan dengan model yang cantik.

Dmitry Shevchenko
sumber
2

Ini semacam denormalisasi. Lihat solusi cantik ini . Definisi bidang komposisi di tempat.

Alex Koshelev
sumber
1

Tambahan kecil dari dokumen Django tentang penghapusan massal ( .delete()metode pada QuerySetobjek):

Perlu diingat bahwa ini akan, jika memungkinkan, dijalankan murni dalam SQL, sehingga metode delete () dari instance objek individual tidak perlu dipanggil selama proses. Jika Anda telah menyediakan metode delete () khusus pada kelas model dan ingin memastikan bahwa itu dipanggil, Anda perlu menghapus instance model itu "secara manual" (misalnya, dengan mengulangi QuerySet dan memanggil delete () pada setiap objek satu per satu) daripada menggunakan metode delete () massal dari QuerySet.

https://docs.djangoproject.com/en/1.11/topics/db/queries/#deleting-objects

Dan pembaruan massal ( .update()metode pada QuerySetobjek):

Terakhir, sadari bahwa update () melakukan update pada level SQL dan, dengan demikian, tidak memanggil metode save () apa pun pada model Anda, juga tidak memancarkan sinyal pre_save atau post_save (yang merupakan konsekuensi dari pemanggilan Model.save ( )). Jika Anda ingin memperbarui sekumpulan record untuk model yang memiliki metode save () khusus, putar ulang dan panggil save ()

https://docs.djangoproject.com/en/2.1/ref/models/querysets/#update

valex
sumber
Bukankah ini berlaku untuk keduanya?
Flimm