Клонировать унаследованный экземпляр модели django

Когда я клонировал экземпляр модели 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):

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>]

Я нахожу это очень уродливым, есть ли более хороший способ клонировать экземпляр из унаследованной модели?

Ответ 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