如何克隆一个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()