Foo.objects.get(pk="foo")
<Foo: test>
在数据库中,我想添加另一个对象,它是上面对象的副本。
假设我的表有一行。我想将第一行对象插入到具有不同主键的另一行中。我该怎么做?
Foo.objects.get(pk="foo")
<Foo: test>
在数据库中,我想添加另一个对象,它是上面对象的副本。
假设我的表有一行。我想将第一行对象插入到具有不同主键的另一行中。我该怎么做?
只需更改您对象的主键并运行save()即可。
obj = Foo.objects.get(pk=<some_existing_pk>)
obj.pk = None
obj.save()
如果你想要自动生成键值,就将新的键值设为None。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()
创建副本。None
,虽然没有直接强调。因此,我的回答主要是强调该方法是Django推荐的方法。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'])
。 - georgebrock这里有一个克隆代码片段(在这里),你可以添加到你的模型中来实现此操作:
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
,即_meta.pk
实例的name
属性。 - Chrisstable
而不是版本号,就像这样:https://docs.djangoproject.com/en/stable/topics/db/queries/#copying-model-instances - Flimmimport 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
copy.copy
,使您可以继续使用原始实例。即使您不打算重用该实例,如果您克隆的实例作为参数传递给函数,则执行此步骤可能更安全。如果没有这样做,当函数返回时调用者将意外地拥有不同的实例。
copy.copy
似乎以所需的方式产生 Django 模型实例的浅复制。这是我没有找到记录的事情之一,但它通过 pickling 和 unpickling 工作,因此它可能得到了很好的支持。_prefetched_objects_cache
是一个快速而粗略的方法,可以去除所有预取。随后的多对多访问的效果就好像从未进行过预取一样。使用以下划线开头的未记录属性可能会导致兼容性问题,但现在可以使用。_[model_name]_cache
的属性,一旦删除,我就能为相关模型分配一个新的ID,然后调用save()
。仍然可能存在我尚未确定的副作用。 - trpt4himd = Foo.objects.filter(pk=1).values().first()
d.update({'id': None})
duplicate = Foo.objects.create(**d)
将pk设置为None更好,因为Django可以正确地为您创建一个pk。
object_copy = MyObject.objects.get(pk=...)
object_copy.pk = None
object_copy.save()
这将进行内存中的复制,您可以独立地对其进行变异。
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
pk
和 id
,保存克隆对象实际上会更新它。 - The-null-Pointer-clone.pk = None
。(我建议使用pk
而不是id
,以防主键是其他字段,例如:uuid
)。 - WhyNotHugo
obj.pk
和obj.id
。 - Petr Pellerdatetime
字段,它将会改变。 - suhailvs