Saya telah bertemu dengan beberapa gotcha dengan jawaban yang diterima. Ini solusinya.
import copy
def clone(instance):
cloned = copy.copy(instance) # don't alter original instance
cloned.pk = None
try:
delattr(cloned, '_prefetched_objects_cache')
except AttributeError:
pass
return cloned
Catatan: ini menggunakan solusi yang tidak disetujui secara resmi di dokumen Django, dan mereka mungkin berhenti bekerja di versi mendatang. Saya menguji ini di 1.9.13.
Peningkatan pertama adalah memungkinkan Anda untuk terus menggunakan contoh asli, dengan menggunakan copy.copy
. Bahkan jika Anda tidak berniat untuk menggunakan kembali instance, itu bisa lebih aman untuk melakukan langkah ini jika instance yang Anda kloning dilewatkan sebagai argumen untuk suatu fungsi. Jika tidak, penelepon secara tak terduga akan memiliki instance yang berbeda ketika fungsi kembali.
copy.copy
tampaknya menghasilkan salinan dangkal contoh model Django dengan cara yang diinginkan. Ini adalah salah satu hal yang saya tidak menemukan didokumentasikan, tetapi bekerja dengan pengawetan dan pembongkaran, sehingga mungkin didukung dengan baik.
Kedua, jawaban yang disetujui akan meninggalkan hasil prefetch yang melekat pada instance baru. Hasil-hasil itu tidak boleh dikaitkan dengan instance baru, kecuali jika Anda secara eksplisit menyalin ke-banyak hubungan. Jika Anda melintasi hubungan yang diambil sebelumnya, Anda akan mendapatkan hasil yang tidak cocok dengan database. Melanggar kode yang berfungsi saat Anda menambahkan prefetch bisa menjadi kejutan yang tidak menyenangkan.
Menghapus _prefetched_objects_cache
adalah cara cepat dan kotor untuk menghapus semua prefetch. Akses ke-banyak berikutnya berfungsi seolah-olah tidak pernah ada prefetch. Menggunakan properti tidak berdokumen yang dimulai dengan garis bawah mungkin meminta masalah kompatibilitas, tetapi berfungsi untuk saat ini.