Dokumen Django hanya mencantumkan contoh untuk menimpa save()
dan delete()
. Namun, saya ingin mendefinisikan beberapa pemrosesan tambahan untuk model saya hanya saat model dibuat . Bagi siapa pun yang akrab dengan Rails, itu akan sama dengan membuat :before_create
filter. Apakah ini mungkin?
django
django-models
django-forms
ground5hark
sumber
sumber
create
? Itu adalah solusi yang menarik, tetapi tidak akan berhasil jika objek dibuat menggunakanObject(**kwargs).save()
atau variasi lain apa pun darinya .super(MyModel, self).save(*args, **kwargs)
?self.pk
bukanlah pilihan terbaik untuk memeriksa apakah objek tersebut baru dibuat atau hanya memperbarui. Kadang-kadang Anda memberikan id objek dalam waktu pembuatan (nilai yang dihasilkan non-database yang disesuaikan sepertiKSUID
), dan itu akan menyebabkan klausa ini tidak pernah dieksekusi ... Adaself._state.adding
nilai untuk memastikan apakah itu menyimpan untuk pertama kali atau hanya memperbarui, yang mana membantu dalam kasus tersebut.Ini sudah tua, memiliki jawaban yang diterima yang berfungsi (Zach), dan yang lebih idiomatik juga (Michael Bylstra), tetapi karena ini masih hasil pertama di Google yang dilihat kebanyakan orang, saya pikir kita membutuhkan praktik terbaik modern-django gaya jawaban di sini :
from django.db.models.signals import post_save class MyModel(models.Model): # ... @classmethod def post_create(cls, sender, instance, created, *args, **kwargs): if not created: return # ...what needs to happen on create post_save.connect(MyModel.post_create, sender=MyModel)
Intinya begini:
@classmethod
bukan@staticmethod
karena kemungkinan besar Anda akan perlu merujuk anggota kelas statis dalam kodeBahkan lebih bersih jika inti Django memiliki
post_create
sinyal yang sebenarnya . (Imho jika Anda perlu meneruskan argumen boolean untuk mengubah perilaku suatu metode, itu harus menjadi 2 metode.)sumber
contoh cara membuat sinyal post_save (dari http://djangosnippets.org/snippets/500/ )
from django.db.models.signals import post_save from django.dispatch import receiver @receiver(post_save, sender=User) def create_profile(sender, instance, created, **kwargs): """Create a matching profile whenever a user object is created.""" if created: profile, new = UserProfile.objects.get_or_create(user=instance)
berikut adalah diskusi yang bijaksana tentang apakah yang terbaik untuk menggunakan sinyal atau metode penyimpanan kustom https://web.archive.org/web/20120815022107/http://www.martin-geber.com/thought/2007/10/29/ django-signal-vs-custom-save-method /
Menurut pendapat saya, menggunakan sinyal untuk tugas ini lebih kuat, lebih mudah dibaca tetapi lebih panjang.
sumber
instance.save()
. Jadi dalam kasus ini, ada juga penalti kinerja karena akan ada satu kueri INSERT dan satu UPDATE ke database.Untuk menjawab pertanyaan secara harfiah,
create
metode dalam manajer model adalah cara standar untuk membuat objek baru di Django. Untuk mengganti, lakukan sesuatu sepertifrom django.db import models class MyModelManager(models.Manager): def create(self, **obj_data): # Do some extra stuff here on the submitted data before saving... # For example... obj_data['my_field'] = my_computed_value(obj_data['my_other_field']) # Now call the super method which does the actual creation return super().create(**obj_data) # Python 3 syntax!! class MyModel(models.model): # An example model my_field = models.CharField(max_length=250) my_other_field = models.CharField(max_length=250) objects = MyModelManager()
Dalam contoh ini, saya mengganti metode
create
metode Manajer untuk melakukan beberapa pemrosesan tambahan sebelum instance benar-benar dibuat.CATATAN: Kode seperti
my_new_instance = MyModel.objects.create(my_field='my_field value')
akan menjalankan
create
metode yang dimodifikasi ini , tetapi kode sukamy_new_unsaved_instance = MyModel(my_field='my_field value')
tidak akan.
sumber
Mengganti
__init__()
akan memungkinkan Anda untuk mengeksekusi kode saat model dibuat. Jangan lupa menelepon orang tua__init__()
.sumber
Anda dapat mengganti metode buat dengan pengelola khusus atau menambahkan metode kelas pada kelas model. https://docs.djangoproject.com/en/1.11/ref/models/instances/#creating-objects
sumber
Jawaban yang disukai benar tetapi pengujian untuk mengetahui apakah objek sedang dibuat tidak berfungsi jika model Anda berasal dari UUIDModel. Bidang pk sudah memiliki nilai.
Dalam hal ini, Anda dapat melakukan ini:
already_created = MyModel.objects.filter(pk=self.pk).exists()
sumber