如何克隆一个Django模型实例对象并将其保存到数据库?

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

在数据库中,我想添加另一个对象,它是上面的对象的副本。

假设我的表有一行。 我想插入第一行对象到不同的主键的另一行。 我怎样才能做到这一点?

只需更改对象的主键并运行save()。

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

如果您想要自动生成密钥,请将新密钥设置为无。

更多关于更新/插入这里 。

用于数据库查询的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()创build原始对象,第二个save()创build该拷贝。

如果你继续阅读文档,还有一些关于如何处理两个更复杂的情况的例子:(1)复制一个作为模型子类实例的对象,(2)也复制相关的对象,包括多对象多种关系。


注意miah的回答:在miah的回答中提到了将pk设置为None ,尽pipe它没有在前面和中间显示。 所以我的回答主要是强调这个方法,作为Django推荐的方法。

历史logging:在版本1.4之前,Django文档中没有对此进行解释。 不过,从1.4之前就已经有可能了。

可能的未来function:上述文档更改是在这张票上进行的 。 在票的评论线上,还有一些关于为模型类添加内置copy函数的讨论,但就我所知他们决定不解决这个问题。 所以这种“手动”的复制方式现在可能要做。

在这里小心点。 如果您处于某种循环,并且您逐个检索对象,这可能会非常昂贵。 如果你不想调用数据库,只需要:

 from copy import deepcopy new_instance = deepcopy(object_you_want_copied) new_instance.id = None new_instance.save() 

它和其他一些答案一样,但是它不会使数据库调用来检索一个对象。 如果要制作数据库中尚不存在的对象的副本,这也很有用。

这里有一个克隆片段,你可以将它添加到你的模型中:

 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/#copying-model-instances

官方的答案与miah的答案类似,但是文档指出了inheritance和相关对象的一些困难,所以你应该确保你阅读文档。

使用下面的代码:

 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) 

设置pk为None更好,sinse Django可以正确地为您创build一个pk

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

要克隆具有多个inheritance级别的模型,即> = 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) 

请参考这里的问题。

尝试这个

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