Django Clone
django-clone is a Django library that facilitates the creation of a deep clone of a Django model instance, including its related objects (Foreign Keys, One-to-One, Many-to-Many). It handles unique fields and provides flexibility for custom attribute overrides during cloning. The current version is 5.5.0, and it maintains an active development pace with regular updates.
Common errors
-
IntegrityError: duplicate key value violates unique constraint "appname_modelname_fieldname_key"
cause Attempting to clone an instance where a field with `unique=True` is not overridden, leading to a duplicate value.fixPass a new unique value for the conflicting field using the `attrs` argument: `clone_instance(original_instance, attrs={'unique_field': 'new_unique_value'})`. -
AttributeError: module 'django_clone' has no attribute 'clone_model_instance'
cause This typically occurs when upgrading to `django-clone` 5.0.0 or later and still using the old import path and function name.fixUpdate your import statement from `from django_clone.utils import clone_model_instance` to `from django_clone import clone_instance`. -
AttributeError: 'Manager' object has no attribute 'clone_instance'
cause The `clone_instance` function expects a model *instance* as its first argument, not a QuerySet manager (e.g., `MyModel.objects`).fixCall `clone_instance` on an actual model instance, e.g., `my_instance = MyModel.objects.get(pk=1)`; then `clone_instance(my_instance, ...)`.
Warnings
- breaking The main cloning function `clone_model_instance` was renamed to `clone_instance` and moved from `django_clone.utils` to the top-level `django_clone` package in version 5.0.0.
- breaking The `shallow` parameter of the cloning function was removed in version 5.0.0. Deep cloning of related objects is now the default behavior, and granular control is managed via `attrs` and signals.
- gotcha Cloning an instance with `unique=True` fields will raise an `IntegrityError` if the unique field's value is not overridden or set to `None` (if nullable) in the `attrs` argument.
- gotcha By default, `django-clone` attempts to deep clone related objects (ForeignKey, OneToOne, ManyToMany). While powerful, this can lead to unintended duplication if you meant to link to existing related objects or if the related objects themselves have complex unique constraints.
Install
-
pip install django-clone
Imports
- clone_instance
from django_clone.utils import clone_model_instance
from django_clone import clone_instance
Quickstart
import os
from django.db import models
from django_clone import clone_instance
# Minimal Django setup for runnable example
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')
import django
django.setup()
class Author(models.Model):
name = models.CharField(max_length=100)
def __str__(self):
return self.name
class Book(models.Model):
title = models.CharField(max_length=100)
isbn = models.CharField(max_length=13, unique=True, null=True, blank=True)
description = models.TextField(blank=True)
author = models.ForeignKey(Author, on_delete=models.CASCADE, related_name='books')
def __str__(self):
return self.title
# Create some initial instances
author1 = Author.objects.create(name="Jane Doe")
original_book = Book.objects.create(
title="The Original Story",
isbn="1234567890123",
description="A timeless classic.",
author=author1
)
# Clone the book instance, providing a new unique ISBN
cloned_book = clone_instance(original_book, attrs={'isbn': '9876543210987', 'title': 'The Cloned Story'})
print(f"Original Book: {original_book.title} (ISBN: {original_book.isbn}, Author: {original_book.author.name})")
print(f"Cloned Book: {cloned_book.title} (ISBN: {cloned_book.isbn}, Author: {cloned_book.author.name})")