programing

Django 모델 인스턴스 개체를 복제하여 데이터베이스에 저장하려면 어떻게 해야 합니까?

sourcejob 2022. 10. 25. 17:48
반응형

Django 모델 인스턴스 개체를 복제하여 데이터베이스에 저장하려면 어떻게 해야 합니까?

Foo.objects.get(pk="foo")
<Foo: test>

데이터베이스에 위의 오브젝트를 복사한 다른 오브젝트를 추가하고 싶습니다.

내 테이블에 열이 하나 있다고 가정해봐.첫 번째 행 개체를 다른 기본 키로 다른 행에 삽입하려고 합니다.내가 어떻게 그럴 수 있을까?

오브젝트의 프라이머리 키를 변경하고 save()를 실행합니다.

obj = Foo.objects.get(pk=<some_existing_pk>)
obj.pk = None
obj.save()

키를 자동으로 생성하는 경우 새 키를 없음으로 설정합니다.

업데이트/삽입에 대한 자세한 내용은 여기를 참조하십시오.

모델 인스턴스 복사에 관한 공식 문서:https://docs.djangoproject.com/en/2.2/topics/db/queries/ #syslog-model-syslog

데이터베이스 쿼리용 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()복사가 생성됩니다.

매뉴얼을 계속 읽다 보면 (1) 모델 서브클래스의 인스턴스인 오브젝트 복사와 (2) 다대다 관계 오브젝트를 포함한 관련 오브젝트 복사라는 두 가지 복잡한 경우의 처리 방법에 대한 예도 있습니다.


에 대한 : 를 miah로 합니다.Nonemiah의 .그래서 저는 그 방법을 장고가 추천하는 방법이라고 주로 강조하고 있습니다.

이력 메모:이것은 버전 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)

여기 클론 스니펫이 있습니다.클론 스니펫을 모델에 추가하여 다음과 같이 할 수 있습니다.

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)

이를 수행하는 방법은 Django1.4의 공식 Django 문서에 추가되었습니다.

https://docs.djangoproject.com/en/1.10/topics/db/queries/ #syslog-model-syslog

공식적인 답변은 Miah의 답변과 비슷하지만, 의사들은 상속과 관련된 물건에 대해 몇 가지 어려움을 지적하고 있기 때문에, 여러분은 그 문서를 꼭 읽어야 할 것입니다.

나는 받아들여진 답을 가진 몇 명의 고추를 우연히 만났다.제 해결책은 이렇습니다.

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모든 프리페치를 빠르게 제거할 수 있습니다.후속 투 다 액세스는 프리페치가 없었던 것처럼 동작합니다.언더스코어로 시작하는 문서화되어 있지 않은 속성을 사용하는 것은 호환성 문제를 요구하는 것일 수 있지만 현재로서는 문제가 없습니다.

pk를 없음으로 설정하는 것이 좋습니다.sinse Django는 올바르게 pk를 생성할 수 있습니다.

object_copy = MyObject.objects.get(pk=...)
object_copy.pk = None
object_copy.save()

이는 모델 인스턴스를 복제하는 또 다른 방법입니다.

d = Foo.objects.filter(pk=1).values().first()   
d.update({'id': None})
duplicate = Foo.objects.create(**d)

이것에 의해, 개별적으로 변환 가능한 메모리내 카피가 실행됩니다.

original = CheckoutItem(title="test", ...)
copy = CheckoutItem()

for f in CheckoutItem._meta.fields:
   setattr(copy, f.attname, getattr(original, f.attname))

또는 방법으로서:


    def clone(self):
        """Returns a clone of this instance."""

        clone = self.__class__()
        for f in self.__class__._meta.fields:
            setattr(clone, f.attname, getattr(self, f.attname))

        return clone

여러 상속 수준(예: >= 2, 또는 아래의 모델 C)을 가진 모델을 복제하려면

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)

여기 질문을 참조해 주세요.

이거 드셔보세요

original_object = Foo.objects.get(pk="foo")
v = vars(original_object)
v.pop("pk")
new_object = Foo(**v)
new_object.save()

django 관리 사이트 내에 UI를 작성하는 패키지가 있습니다.https://github.com/RealGeeks/django-modelclone

pip install django-modelclone

INSTALLED_에 "모델 클론" 추가APPS 및 admin.py로 Import합니다.

그런 다음 모델을 클로닝할 수 있도록 하려면 "admin"을 바꿉니다.지정된 관리 모델 클래스 "modelclone"의 ModelAdmin"입니다.Clonable Model Admin"을 클릭합니다.그러면 해당 모델의 인스턴스 세부 정보 페이지에 "복제" 버튼이 나타납니다.

를 가지고 있는 경우OneToOneField다음 방법으로 해야 합니다.

    tmp = Foo.objects.get(pk=1)
    tmp.pk = None
    tmp.id = None
    instance = tmp

이 간단한 프로세스로 문제없이 동작합니다.

foo_obj = Foo.objects.get(pk="foo")
foo_values = foo_obj.__dict__
foo_values.pop('_state')
foo_values.pop('id')
foo_new_obj = Foo(**foo_values)
foo_new_obj.save()

언급URL : https://stackoverflow.com/questions/4733609/how-do-i-clone-a-django-model-instance-object-and-save-it-to-the-database

반응형