2013-04-09 3 views
5

Когда я клонировал экземпляр модели django, я использовал для очистки поля «pk». Это, кажется, не работать с унаследованной моделью:Клонировать унаследованный экземпляр модели django

Возьмите это:

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) 

Теперь давайте создадим экземпляр и клонировать его на «обычным» способом (я использую Джанго оболочки):

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

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

+0

Будете ли вы использовать базовые модели самостоятельно или вы будете использовать только модель, которая наследуется от них? Если вам не нужно использовать базовые модели самостоятельно, тогда это должно работать, чтобы использовать [абстрактные базовые классы] (https://docs.djangoproject.com/en/dev/topics/db/models/#abstract-base -классов). –

+0

На самом деле наследование в моделях Django можно считать плохой практикой, вы можете использовать абстрактные базовые классы или внешние ключи. – PepperoniPizza

+0

Можете ли вы вставить свой метод save(), как вы устанавливаете pk на модели? – PepperoniPizza

ответ

0
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 всегда будет одним и тем же объектом. Если вы хотите клонировать его, вам нужно создать новый объект. Либо с помощью конструктора в моделька:

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) 

Тогда с2 и с будут идентичны, несмотря на их рк

Смежные вопросы