I\'ve models for Books
, Chapters
and Pages
. They are all written by a User
:
from django.db import models
Elaborated based on previous answers:
def derive(obj):
import copy
from django.contrib.admin.utils import NestedObjects
from django.db import DEFAULT_DB_ALIAS
from django.db.models.fields.related import ForeignKey
"""
Derive a new model instance from previous one,
and duplicate all related fields to point to the new instance
"""
obj2 = copy.copy(obj)
obj2.pk = None
obj2.save()
collector = NestedObjects(using=DEFAULT_DB_ALIAS)
collector.collect([obj])
collector.sort()
related_models = collector.data.keys()
data_snapshot = {}
for key in collector.data.keys():
data_snapshot.update({
key: dict(
zip(
[item.pk for item in collector.data[key]],
[item for item in collector.data[key]]
)
)
})
duplicate_order = reversed(related_models)
for model in duplicate_order:
# Find all FKs on model that point to a related_model.
fks = []
for f in model._meta.fields:
if isinstance(f, ForeignKey) and f.rel.to in related_models:
fks.append(f)
# Replace each `sub_obj` with a duplicate.
if model not in collector.data:
continue
sub_objects = collector.data[model]
for obj in sub_objects:
for fk in fks:
dupe_obj = copy.copy(obj)
setattr(dupe_obj, fk.name, obj2)
dupe_obj.pk = None
dupe_obj.save()
return obj2
Django does have a built-in way to duplicate an object via the admin - as answered here: In the Django admin interface, is there a way to duplicate an item?
Suggestion of Julio Marins works! Thnx!
For Django >= 2.* this line:
if isinstance(f, ForeignKey) and f.rel.to in related_models:
Should be replaced with:
if isinstance(f, ForeignKey) and f.remote_field.model in related_models:
In Django 1.5 this works for me:
thing.id = None
thing.pk = None
thing.save()
Here's an easy way to copy your object.
Basically:
(1) set the id of your original object to None:
book_to_copy.id = None
(2) change the 'author' attribute and save the ojbect:
book_to_copy.author = new_author
book_to_copy.save()
(3) INSERT performed instead of UPDATE
(It doesn't address changing the author in the Page--I agree with the comments regarding re-structuring the models)