답변:
객체의 기본 키를 변경하고 save ()를 실행하십시오.
obj = Foo.objects.get(pk=<some_existing_pk>)
obj.pk = None
obj.save()
자동 생성 키를 원하면 새 키를 없음으로 설정하십시오.
UPDATE / INSERT에 대한 자세한 내용은 여기를 참조하십시오 .
모델 인스턴스 복사에 대한 공식 문서 : https://docs.djangoproject.com/en/2.2/topics/db/queries/#copying-model-instances
obj.pk
obj.id
데이터베이스 쿼리에 대한 Django 설명서에는 모델 인스턴스 복사에 대한 섹션이 포함되어 있습니다. 기본 키가 자동 생성되었다고 가정하면 복사하려는 객체를 가져 None
오고 기본 키를로 설정 한 후 객체를 다시 저장합니다.
blog = Blog(name='My blog', tagline='Blogging is easy')
blog.save() # blog.pk == 1
blog.pk = None
blog.save() # blog.pk == 2
이 스 니펫에서 첫 번째 save()
는 원본 객체를 save()
만들고 두 번째 는 사본을 만듭니다.
문서를 계속 읽으면 두 가지 더 복잡한 경우를 처리하는 방법에 대한 예도 있습니다. -많은 관계.
miah의 답변에 대한 참고 사항 : pk를 설정하는 None
것은 miah의 답변에 언급되어 있지만 앞면과 가운데에는 나와 있지 않습니다. 그래서 제 대답은 주로 장고 권장 방법으로 그 방법을 강조하는 것입니다.
역사적 참고 사항 : 이것은 장고 문서에서 1.4 버전까지 설명되지 않았습니다. 그러나 1.4 이전부터 가능했습니다.
향후 기능 가능 : 위에서 언급 한 문서 변경 사항 이이 티켓 에서 변경되었습니다 . 티켓의 주석 스레드에서 copy
모델 클래스 에 내장 함수를 추가하는 것에 대한 토론도 있었지만 아는 한 아직 그 문제를 해결하지 않기로 결정했습니다. 따라서이 "수동"복사 방법은 아마도 지금해야 할 것입니다.
여기서 조심하십시오. 어떤 종류의 루프에 있고 객체를 하나씩 검색하는 경우 이것은 매우 비쌀 수 있습니다. 데이터베이스를 호출하지 않으려면 다음을 수행하십시오.
from copy import deepcopy
new_instance = deepcopy(object_you_want_copied)
new_instance.id = None
new_instance.save()
이 다른 답변 중 일부와 동일한 작업을 수행하지만 객체를 검색하기 위해 데이터베이스를 호출하지는 않습니다. 데이터베이스에 아직 존재하지 않는 개체의 복사본을 만들려는 경우에도 유용합니다.
아래 코드를 사용하십시오 :
from django.forms import model_to_dict
instance = Some.objects.get(slug='something')
kwargs = model_to_dict(instance, exclude=['id'])
new_instance = Some.objects.create(**kwargs)
model_to_dict
소요 exclude
당신이 별도 필요하지 않은 수단 매개 변수 pop
:model_to_dict(instance, exclude=['id'])
복제 조각이있다 여기 이 수행 모델에 추가 할 수있는 :
def clone(self):
new_kwargs = dict([(fld.name, getattr(old, fld.name)) for fld in old._meta.fields if fld.name != old._meta.pk]);
return self.__class__.objects.create(**new_kwargs)
if
이제는 인스턴스 if fld.name != old._meta.pk.name
의 name
속성 이어야 _meta.pk
합니다.
이 작업을 수행하는 방법은 Django1.4의 공식 Django 문서에 추가되었습니다
https://docs.djangoproject.com/en/1.10/topics/db/queries/#copying-model-instances
공식적인 대답은 miah의 대답과 비슷하지만 문서는 상속 및 관련 개체에 약간의 어려움이 있음을 나타내므로 문서를 읽으십시오.
stable
은 URL에서 버전 번호 대신 다음과 같이 사용하는 것입니다. docs.djangoproject.com/en/stable/topics/db/queries/…
나는 받아 들인 대답으로 몇 가지 문제에 봉착했습니다. 여기 내 해결책이 있습니다.
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
참고 : 이것은 Django 문서에서 공식적으로 승인되지 않은 솔루션을 사용하며 이후 버전에서는 작동하지 않을 수 있습니다. 나는 이것을 1.9.13에서 테스트했다.
첫 번째 개선 사항은을 사용하여 원본 인스턴스를 계속 사용할 수 있다는 것 copy.copy
입니다. 인스턴스를 재사용하지 않더라도 복제중인 인스턴스가 함수의 인수로 전달 된 경우이 단계를 수행하는 것이 더 안전 할 수 있습니다. 그렇지 않으면 함수가 반환 될 때 호출자가 예기치 않게 다른 인스턴스를 갖게됩니다.
copy.copy
원하는 방식으로 Django 모델 인스턴스의 얕은 사본을 생성하는 것 같습니다. 이것은 내가 문서화하지 않은 것 중 하나이지만 피클 링과 피클 링으로 작동하므로 잘 지원됩니다.
둘째, 승인 된 답변은 프리 페치 된 결과를 새 인스턴스에 첨부합니다. 다 대 관계를 명시 적으로 복사하지 않는 한 이러한 결과는 새 인스턴스와 연관되어서는 안됩니다. 프리 페치 된 관계를 순회하면 데이터베이스와 일치하지 않는 결과가 나타납니다. 프리 페치를 추가 할 때 작업 코드를 깨는 것은 놀라운 일이 아닙니다.
삭제 _prefetched_objects_cache
는 모든 프리 페치를 제거하는 빠르고 더러운 방법입니다. 후속 다 대다 액세스는 프리 페치가없는 것처럼 작동합니다. 밑줄로 시작하는 문서화되지 않은 속성을 사용하는 것은 호환성 문제를 요구할 수도 있지만 현재로서는 효과가 있습니다.
_[model_name]_cache
, 삭제하면, 내가 전화를 한 후, 그 관련 모델에 새로운 ID를 할당 할 수 있었다 save()
. 아직 결정하지 않은 부작용이 여전히있을 수 있습니다.
상속 수준이 여러 개인 모델 (예 :> = 2 또는 아래 ModelC)을 복제하려면
class ModelA(models.Model):
info1 = models.CharField(max_length=64)
class ModelB(ModelA):
info2 = models.CharField(max_length=64)
class ModelC(ModelB):
info3 = models.CharField(max_length=64)