Saya ingin memicu tindakan khusus dalam metode save () dari objek model Django ketika saya menyimpan catatan baru (tidak memperbarui catatan yang ada.)
Apakah pemeriksaan untuk (self.id! = Tidak ada) diperlukan dan memadai untuk menjamin bahwa catatan diri itu baru dan tidak diperbarui? Adakah kasus khusus yang mungkin diabaikan?
django
django-models
MikeN
sumber
sumber
UUIDField pk
Jawaban:
Diperbarui: Dengan klarifikasi yang
self._state
bukan variabel instance pribadi, tetapi dinamai demikian untuk menghindari konflik, pengecekanself._state.adding
sekarang merupakan cara yang lebih baik untuk memeriksa.mengembalikan True dalam objek Model baru, kecuali objek tersebut memiliki
UUIDField
sebagaiprimary_key
.Kasus sudut yang mungkin harus Anda khawatirkan adalah apakah ada batasan keunikan pada bidang selain id (misalnya, indeks unik sekunder di bidang lain). Dalam hal ini, Anda masih dapat memiliki catatan baru di tangan, tetapi tidak dapat menyimpannya.
sumber
is not
daripada!=
ketika memeriksa identitas denganNone
objekmodels.OneToOneField(OtherModel, primary_key=True)
. Saya pikir Anda perlu menggunakanself.pk
UUIDField
kunci utama,self.pk
tidak pernahNone
.Cara alternatif untuk memeriksa
self.pk
kita dapat memeriksaself._state
modelself._state.adding is True
menciptakanself._state.adding is False
memperbaruiSaya mendapatkannya dari halaman ini
sumber
self._state.adding
kerjanya, tetapi peringatan yang adil bahwa tampaknya selalu samaFalse
jika Anda memeriksanya setelah meneleponsuper(TheModel, self).save(*args, **kwargs)
: github.com/django/django/blob/stable/1.10.x/django/db/models/ ..._state
tidak pribadi; seperti_meta
, diawali dengan garis bawah untuk menghindari kebingungan dengan nama bidang. (Perhatikan bagaimana ini digunakan dalam dokumentasi yang ditautkan.)is_new = self._state.adding
, kemudiansuper(MyModel, self).save(*args, **kwargs)
dan kemudianif is_new: my_custom_logic()
Memeriksa
self.id
mengasumsikan bahwa ituid
adalah kunci utama untuk model. Cara yang lebih umum adalah dengan menggunakan pintasan pk .is_new = self.pk is None
sumber
super(...).save()
.Cek untuk
self.pk == None
ini tidak cukup untuk menentukan apakah objek tersebut akan dimasukkan atau diperbarui dalam database.Django O / RM menampilkan peretasan jahat yang pada dasarnya untuk memeriksa apakah ada sesuatu pada posisi PK dan jika demikian lakukan PEMBARUAN, jika tidak lakukan INSERT (ini akan dioptimalkan menjadi INSERT jika PK Tidak Ada).
Alasan mengapa harus melakukan ini adalah karena Anda diizinkan untuk mengatur PK ketika suatu objek dibuat. Meskipun tidak umum di mana Anda memiliki kolom urutan untuk kunci utama, ini tidak berlaku untuk jenis bidang kunci utama lainnya.
Jika Anda benar-benar ingin tahu, Anda harus melakukan apa yang dilakukan O / RM dan mencari di database.
Tentu saja Anda memiliki kasus khusus dalam kode Anda dan untuk itu sangat mungkin
self.pk == None
memberi tahu Anda semua yang perlu Anda ketahui, tetapi itu bukan solusi umum.sumber
UUIDField
sebagai Kunci Utama: kunci tidak diisi pada tingkat DB, jadiself.pk
selaluTrue
.Anda bisa saja terhubung ke sinyal post_save yang mengirimkan kwarg "dibuat", jika benar, objek Anda telah dimasukkan.
http://docs.djangoproject.com/en/stable/ref/signals/#post-save
sumber
ATOMIC_REQUESTS
, jadi saya tidak begitu yakin tentang default.Periksa
self.id
danforce_insert
benderanya.Ini berguna karena objek (diri) Anda yang baru dibuat memiliki
pk
nilaisumber
Saya sangat terlambat untuk percakapan ini, tetapi saya mengalami masalah dengan self.pk yang sedang diisi ketika memiliki nilai default yang terkait dengannya.
Cara saya menyiasatinya adalah menambahkan bidang date_created ke model
date_created = models.DateTimeField(auto_now_add=True)
Dari sini kamu bisa pergi
created = self.date_created is None
sumber
Untuk solusi yang juga berfungsi bahkan ketika Anda memiliki
UUIDField
sebagai kunci utama (yang seperti yang dicatat orang lain tidakNone
jika Anda hanya menimpanyasave
), Anda dapat mencolokkan sinyal post_save Django . Tambahkan ini ke models.py Anda :Callback ini akan memblokir
save
metode ini, sehingga Anda dapat melakukan hal-hal seperti memicu notifikasi atau memperbarui model lebih lanjut sebelum respons Anda dikirim kembali melalui kabel, apakah Anda menggunakan formulir atau kerangka Django REST untuk panggilan AJAX. Tentu saja, gunakan secara bertanggung jawab dan bongkar tugas berat ke antrian pekerjaan alih-alih membuat pengguna Anda menunggu :)sumber
alih-alih gunakan pk alih-alih id :
sumber
Ini adalah cara umum untuk melakukannya.
id akan diberikan saat disimpan pertama kali ke db
sumber
Apakah ini akan berhasil untuk semua skenario di atas?
sumber
sumber
Untuk mengetahui apakah Anda memperbarui atau memasukkan objek (data), gunakan
self.instance.fieldname
di formulir Anda. Tentukan fungsi bersih dalam formulir Anda dan periksa apakah entri nilai saat ini sama dengan sebelumnya, jika tidak maka Anda memperbaruinya.self.instance
danself.instance.fieldname
bandingkan dengan nilai barusumber