Using Django 1.9 and Python 3.4 I want to copy an existing model instance and all its related data. Below is an example of how I have currently achieved this. My question is, is there a better way?
I have read over posts e.g. Duplicating model instances and their related objects in Django / Algorithm for recusrively duplicating an object this one but, they are over 8 years old and no longer work with Django 1.9+.
Below is how I try to achieve this already, ok or a better way in Django 1.9?
Models
class Book(models.Model):
name = models.CharField(max_length=80)
class Contributor(models.Model):
name = models.CharField(max_length=80)
books = models.ForeignKey("Book", related_name="contributors")
The copy function. I have to recreate contributors after saving the new Book instance otherwise, it will assign existing contributors from the instance I'm copying from.
def copy_book(self, id):
view = self.context['view']
book_id = id
book = Book.objects.get(pk=book_id)
copy_book_contributors = book.contributors.all()
book.id = None
# make a copy of the contributors items.
book.save()
for item in copy_book_contributors:
# We need to copy/save the item as it will reassign the existing one.
item.id = None
item.save()
book.contributors.add(item)
There is no built-in method for copying model instances, it is possible to create new instance with all fields values copied. If an instance is saved with instance's pk set to None , the instance is used to create a new record in the DB. That means every field other than the PK is copied.
The all() method returns a QuerySet of all the objects in the database.
Models inheritance works the same way as normal Python class inheritance works, the only difference is, whether we want the parent models to have their own table in the database or not. When the parent model tables are not created as tables it just acts as a container for common fields and methods.
For this particular case, you can bulk_create
the contributors
:
contributor_names = list(book.contributors.values_list('name', flat=True))
book.id = None
book.save()
# create the contributor object with the name and new book id.
contributors = [Contributor(name=name, book_id=book.id) for name in contributor_names]
Contributor.objects.bulk_create(contributors)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With