FYI, on_delete
parameter dalam model mundur dari apa yang terdengar. Anda mengenakan on_delete
Kunci Asing (FK) pada model untuk memberi tahu Django apa yang harus dilakukan jika entri FK yang Anda tunjuk pada catatan Anda dihapus. Pilihan toko kami telah menggunakan sebagian besar PROTECT
, CASCADE
dan SET_NULL
. Berikut adalah aturan dasar yang saya temukan:
- Gunakan
PROTECT
saat FK Anda menunjuk ke tabel pencarian yang benar-benar tidak boleh berubah dan yang pasti tidak menyebabkan meja Anda berubah. Jika ada yang mencoba menghapus entri pada tabel pencarian itu, PROTECT
mencegah mereka menghapusnya jika dikaitkan dengan catatan apa pun. Ini juga mencegah Django dari menghapus catatan Anda hanya karena menghapus entri pada tabel pencarian. Bagian terakhir ini sangat penting. Jika seseorang menghapus jenis kelamin "Perempuan" dari tabel Gender saya, saya PASTI TIDAK ingin itu menghapus secara instan siapa saja dan semua orang yang saya miliki di tabel Person yang memiliki jenis kelamin itu.
- Gunakan
CASCADE
saat FK Anda menunjuk ke catatan "orang tua". Jadi, jika Seseorang dapat memiliki banyak entri PersonEthnicity (dia bisa menjadi Indian Amerika, Hitam, dan Putih), dan Orang itu dihapus, saya benar - benar ingin entri PersonEthnicity "anak" dihapus. Mereka tidak relevan tanpa Pribadi.
- Gunakan
SET_NULL
ketika Anda melakukan ingin orang diizinkan untuk menghapus entri pada tabel-up, tetapi Anda masih ingin mempertahankan catatan Anda. Sebagai contoh, jika seseorang dapat memiliki HighSchool, tetapi itu tidak masalah bagi saya jika SMA itu hilang di meja saya, saya akan mengatakan on_delete=SET_NULL
. Ini akan meninggalkan catatan Orang saya di luar sana; itu hanya akan membuat FK sekolah menengah pada Orang saya menjadi nol. Jelas, Anda harus mengizinkan null=True
di FK itu.
Berikut adalah contoh model yang melakukan ketiga hal:
class PurchPurchaseAccount(models.Model):
id = models.AutoField(primary_key=True)
purchase = models.ForeignKey(PurchPurchase, null=True, db_column='purchase', blank=True, on_delete=models.CASCADE) # If "parent" rec gone, delete "child" rec!!!
paid_from_acct = models.ForeignKey(PurchPaidFromAcct, null=True, db_column='paid_from_acct', blank=True, on_delete=models.PROTECT) # Disallow lookup deletion & do not delete this rec.
_updated = models.DateTimeField()
_updatedby = models.ForeignKey(Person, null=True, db_column='_updatedby', blank=True, related_name='acctupdated_by', on_delete=models.SET_NULL) # Person records shouldn't be deleted, but if they are, preserve this PurchPurchaseAccount entry, and just set this person to null.
def __unicode__(self):
return str(self.paid_from_acct.display)
class Meta:
db_table = u'purch_purchase_account'
Sebagai berita gembira terakhir, tahukah Anda bahwa jika Anda tidak menentukan on_delete
(atau tidak), perilaku defaultnya adalah CASCADE
? Ini berarti bahwa jika seseorang menghapus entri gender pada tabel Gender Anda, setiap Orang yang mencatat gender tersebut juga akan dihapus!
Saya akan berkata, "Jika ragu, atur on_delete=models.PROTECT
." Lalu, uji aplikasi Anda. Anda akan dengan cepat mengetahui FK mana yang harus diberi label nilai-nilai lain tanpa membahayakan data Anda.
Juga, perlu dicatat bahwa on_delete=CASCADE
sebenarnya tidak ditambahkan ke migrasi Anda, jika itu adalah perilaku yang Anda pilih. Saya kira ini karena itu adalah default, jadi menempatkan on_delete=CASCADE
adalah hal yang sama dengan tidak meletakkan apa pun.