Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to copy a Django Model Instance and all related data

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)
like image 384
MarkK Avatar asked Jan 13 '17 14:01

MarkK


People also ask

How do I copy a model in Django?

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.

How do I get all items in Django ORM?

The all() method returns a QuerySet of all the objects in the database.

Can we inherit models in Django?

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.


1 Answers

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)
like image 89
AKS Avatar answered Oct 12 '22 14:10

AKS