Как дублировать модели Django с помощью отношений OneToOneField
Начните со следующих моделей, используя django==3.2.12:
from django.db import models
class Root(models.Model):
pass
class Leaf(models.Model):
root = models.OneToOneField(Root, related_name='leaf_data', on_delete=models.CASCADE)
Запустите в командной оболочке следующее:
>>> from myapp.models import Root, Leaf
>>> root = Root()
>>> root.save()
>>> leaf = Leaf(root=root)
>>> leaf.save()
>>> root
<Root: Root object (1)>
>>> leaf
<Leaf: Leaf object (1)>
>>> new_root = Root()
>>> new_root.save()
>>> new_root
<Root: Root object (2)>
>>> root.leaf_data
<Leaf: Leaf object (1)>
>>> leaf = root.leaf_data
>>> leaf.pk = None
>>> leaf.root = new_root
>>> leaf.save()
>>> leaf.root
<Root: Root object (2)>
>>> root.leaf_data
<Leaf: Leaf object (2)>
Почему изменяется исходная ссылка root.leaf_data? Я бы ожидал, что при установке leaf.pk = None и leaf.root = new_root исходная структура корень/лист останется нетронутой. Я пытаюсь создать полный дубликат из оригинала.
Я не менял на db. Если вы сделаете root.refresh_from_db() root.leaf_data должно быть <Leaf: Leaf object (1)>.
Что произошло: вы использовали объект root.leaf_data для создания другого листа. После save django гидратировал этот Leaf экземпляр с данными вновь созданного листа - <Leaf: Leaf object (2)>. Но root по-прежнему указывает на этот объект!
Если бы вы создали новый Leaf и не использовали повторно экземпляр, проблема бы не возникла :D