Kabul edilen cevapla bir kaç tane karşılaştım. İşte benim çözümüm.
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
Not: Bu, Django belgelerinde resmi olarak onaylanmayan çözümleri kullanır ve gelecekteki sürümlerde çalışmayı durdurabilir. Bunu 1.9.13'te test ettim.
İlk gelişme, kullanarak orijinal örneği kullanmaya devam etmenize izin vermesidir copy.copy
. Örneği yeniden kullanmak istemeseniz bile, klonladığınız örnek bir işleve argüman olarak iletildiyse bu adımı uygulamak daha güvenli olabilir. Değilse, işlev döndüğünde arayanın beklenmedik şekilde farklı bir örneği olur.
copy.copy
Django model örneğinin sığ bir kopyasını istenen şekilde üretiyor gibi görünüyor. Bu, belgelenmiş bulamadığım şeylerden biri, ancak dekapaj ve unpickling ile çalışıyor, bu yüzden muhtemelen iyi destekleniyor.
İkinci olarak, onaylanan cevap yeni örneğe önceden getirilmiş sonuçları bırakacaktır. Çok sayıda ilişkiyi açıkça kopyalamadığınız sürece bu sonuçlar yeni örnekle ilişkilendirilmemelidir. Önceden getirilmiş ilişkiler arasında geçiş yaparsanız, veritabanıyla eşleşmeyen sonuçlar alırsınız. Bir ön getirme eklediğinizde çalışma kodunu kırmak kötü bir sürpriz olabilir.
Silme _prefetched_objects_cache
, tüm ön getirmeleri ortadan kaldırmanın hızlı ve kirli bir yoludur. Birçok erişimin ardından, önceden getirme yokmuş gibi çalışır. Alt çizgiyle başlayan belgelenmemiş bir özellik kullanmak, muhtemelen uyumluluk sorunu ister, ancak şimdilik çalışıyor.