Foo.objects.get(pk="foo")
<Foo: test>
在数据库中,我想添加另一个对象,这是上面对象的副本。
假设我的表只有一行。我想将第一行对象插入到另一行,使用不同的主键。我该怎么做呢?
Foo.objects.get(pk="foo")
<Foo: test>
在数据库中,我想添加另一个对象,这是上面对象的副本。
假设我的表只有一行。我想将第一行对象插入到另一行,使用不同的主键。我该怎么做呢?
当前回答
这个简单的过程对我来说很有效:
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()
其他回答
只需更改对象的主键并运行save()。
obj = Foo.objects.get(pk=<some_existing_pk>)
obj.pk = None
obj.save()
如果需要自动生成密钥,请将新密钥设置为None。
更多关于更新/插入的信息请点击这里。
关于复制模型实例的官方文档:https://docs.djangoproject.com/en/2.2/topics/db/queries/#copying-model-instances
这将在内存中进行复制,您可以独立地进行突变。
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
试试这个
original_object = Foo.objects.get(pk="foo")
v = vars(original_object)
v.pop("pk")
new_object = Foo(**v)
new_object.save()
我在公认的答案中遇到了一些问题。这是我的解决方案。
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似乎以所需的方式生成Django模型实例的浅拷贝。这是我没有找到文档的东西之一,但它通过pickle和unpickle工作,因此可能得到了良好的支持。
其次,已批准的答案将把任何预取的结果附加到新实例。这些结果不应该与新实例相关联,除非显式地复制“多到多”关系。如果遍历预取的关系,将得到与数据库不匹配的结果。当您添加预取时,破坏工作代码可能是一个令人讨厌的惊喜。
删除_prefetched_objects_cache是去除所有预取的一种快速而肮脏的方法。后续的多路访问就像从来没有预取一样。使用以下划线开头的未记录的属性可能会带来兼容性问题,但目前是可行的。
如何做到这一点被添加到Django官方文档在Django1.4
https://docs.djangoproject.com/en/1.10/topics/db/queries/#copying-model-instances
官方的答案与miah的答案相似,但是文档指出了继承和相关对象的一些困难,所以您应该确保阅读了文档。