克隆一个继承的 django 模型实例

Posted

技术标签:

【中文标题】克隆一个继承的 django 模型实例【英文标题】:Clone an inherited django model instance 【发布时间】:2013-04-01 04:29:32 【问题描述】:

当我克隆一个 django 模型实例时,我用来清理“pk”字段。 这似乎不适用于继承的模型:

拿着这个:

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)

现在让我们创建一个实例并以“通常”的方式克隆它(我使用的是 django shell):

In [1]: c=ModelC(info1="aaa",info2="bbb",info3="ccc")

In [2]: c.save()

In [3]: c.pk
Out[3]: 1L

In [4]: c.pk=None  <------ to clone

In [5]: c.save()   <------ should generate a new instance with a new index key

In [6]: c.pk       
Out[6]: 1L         <------ but don't

In [7]: ModelC.objects.all()
Out[7]: [<ModelC: ModelC object>]   (only one instance !)

我发现的唯一方法是:

In [16]: c.pk =None

In [17]: c.id=None

In [21]: c.modela_ptr_id=None

In [22]: c.modelb_ptr_id=None

In [23]: c.save()

In [24]: c.pk
Out[24]: 2L    <---- successful clone containing info1,info2,info3 from original instance

In [25]: ModelC.objects.all()
Out[25]: [<ModelC: ModelC object>, <ModelC: ModelC object>]

我觉得这很丑,有没有更好的方法从继承的模型中克隆实例?

【问题讨论】:

您将完全使用基本模型还是只使用从它们继承的模型?如果您不需要自己使用基本模型,那么使用abstract base classes应该可以。 其实在 Django 模型中继承可以被认为是一种不好的做法,你可以使用抽象基类,或者外键。 能否请您粘贴您的 save() 方法,您是如何在模型上设置 pk 的? 实际上,在我的程序中,我有几个继承级别,前2个级别是抽象的,然后我有2个其他级别带自己的参数。我打算再做一个,这就是我做这个例子的原因。当我看到生成的表格时,我可能会回到更“常见”的模型模式:只有一个非抽象模型级别。 我正在使用多态模型,将 basemodel_ptr_id 设置为 None 不会为我创建新记录,除非我将 id 设置为 None 以及您显示的内容。 【参考方案1】:
c=ModelC(info1="aaa",info2="bbb",info3="ccc")
# creates an instance

c.save()
# writes instance to db

c.pk=None
# I doubt u can nullify the auto-generated pk of an existing object, because a pk is not nullable
c.save()
# if I'm right nothing will happen here.

所以 c 将永远是同一个对象。如果要克隆它,则需要生成一个新对象。在 ModelC 中使用构造函数:

def __init__(another_modelC_obj=null, self):
   if another_modelC_obj:
      # for every field in another_modelC_obj: do self.field = another_modelC_obj.field
   super().__init__()

这样你就可以走了

c2=ModelC(c)

或者直接调用:

c2=ModelC(c.info1, c.info2, c.info3)

那么 c2 和 c 将是相同的,尽管它们的 pk 不同

【讨论】:

以上是关于克隆一个继承的 django 模型实例的主要内容,如果未能解决你的问题,请参考以下文章

Django模型继承:使用现有超类创建子类

django模型的继承

如何克隆 Django 模型实例对象并在 Django 表单上显示?

在 django 中获取继承的模型对象

django 抽象模型与常规继承

django模型继承中的一致性需求