Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions model_clone/mixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,8 @@ def make_clone(self, attrs=None, sub_clone=False, using=None):
duplicate = self.__duplicate_o2m_fields(duplicate, using=using)
duplicate = self.__duplicate_m2m_fields(duplicate, using=using)

duplicate.save(using=using)

return duplicate

def bulk_clone(
Expand Down
36 changes: 36 additions & 0 deletions model_clone/tests/test_clone_mixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,20 +62,23 @@ def test_cloning_a_transient_instance_is_invalid(self):
def test_cloning_model_with_custom_id(self):
instance = Library.objects.create(name="First library", user=self.user1)
clone = instance.make_clone({"user": self.user2})
clone.refresh_from_db()
self.assertNotEqual(instance.pk, clone.pk)

@patch("sample.models.Library._clone_excluded_fields", new_callable=PropertyMock)
def test_cloning_model_with_excluded_fields(self, _clone_excluded_fields_mock):
_clone_excluded_fields_mock.return_value = ["name"]
instance = Library.objects.create(name="First library", user=self.user1)
clone = instance.make_clone({"name": "New Library"})
clone.refresh_from_db()
self.assertNotEqual(instance.pk, clone.pk)
self.assertNotEqual(instance.name, clone.name)

def test_cloning_explict_fields(self):
name = "New Library"
instance = Library.objects.create(name=name, user=self.user1)
clone = instance.make_clone({"user": self.user2, "name": "New name"})
clone.refresh_from_db()

self.assertEqual(instance.name, name)
self.assertNotEqual(instance.pk, clone.pk)
Expand All @@ -88,13 +91,15 @@ def test_cloning_with_default_value(self, _clone_fields_mock):
)
_clone_fields_mock.return_value = ["name", "created_by", "slug", "published_at"]
clone = instance.make_clone()
clone.refresh_from_db()
self.assertNotEqual(instance.pk, clone.pk)
self.assertEqual(instance.name, clone.name)
self.assertNotEqual(instance.slug, clone.slug)
self.assertIsNone(clone.published_at)

_clone_fields_mock.return_value.remove("published_at")
clone = instance.make_clone()
clone.refresh_from_db()
self.assertNotEqual(instance.pk, clone.pk)
self.assertEqual(instance.name, clone.name)
self.assertNotEqual(instance.slug, clone.slug)
Expand All @@ -104,6 +109,7 @@ def test_cloning_unique_fk_field(self):
name = "New Library"
instance = Library.objects.create(name=name, user=self.user1)
clone = instance.make_clone({"user": self.user2})
clone.refresh_from_db()

self.assertNotEqual(instance.pk, clone.pk)
self.assertNotEqual(instance.user, clone.user)
Expand All @@ -112,6 +118,7 @@ def test_cloning_unique_o2o_field_without_a_fallback_value_is_valid(self):
name = "New Library"
instance = Library.objects.create(name=name, user=self.user1)
clone = instance.make_clone()
clone.refresh_from_db()

self.assertNotEqual(instance.pk, clone.pk)
self.assertNotEqual(instance.user.pk, clone.user.pk)
Expand All @@ -125,6 +132,7 @@ def test_cloning_related_unique_o2o_field_without_a_fallback_value_is_valid(self
)
cover = Cover.objects.create(content="New Cover", book=book)
clone = cover.make_clone()
clone.refresh_from_db()

self.assertNotEqual(cover.pk, clone.pk)
self.assertNotEqual(cover.book.pk, clone.book.pk)
Expand All @@ -139,6 +147,7 @@ def test_cloning_related_unique_o2o_field_without_a_fallback_value_is_valid(self
)
cover = Cover.objects.create(content="New Cover", book=book)
clone = book.make_clone()
clone.refresh_from_db()

self.assertNotEqual(book.pk, clone.pk)
self.assertNotEqual(cover.pk, clone.cover.pk)
Expand All @@ -149,6 +158,7 @@ def test_cloning_related_unique_o2o_field_without_a_fallback_value_is_valid(self
)
backcover = BackCover.objects.create(content="New Back Cover", book=book)
clone = book.make_clone()
clone.refresh_from_db()

self.assertNotEqual(book.pk, clone.pk)
self.assertIsNotNone(clone.backcover.pk)
Expand All @@ -165,6 +175,7 @@ def test_cloning_model_with_a_different_db_alias_is_valid(self):
attrs={"user": new_user, "name": "New name"},
using=self.REPLICA_DB_ALIAS,
)
clone.refresh_from_db()

self.assertEqual(instance.name, name)
self.assertNotEqual(instance.pk, clone.pk)
Expand All @@ -175,6 +186,7 @@ def test_cloning_with_field_overridden(self):
instance = Library.objects.create(name=name, user=self.user1)
new_name = "My New Library"
clone = instance.make_clone(attrs={"name": new_name, "user": self.user2})
clone.refresh_from_db()

self.assertEqual(instance.name, name)

Expand All @@ -191,6 +203,7 @@ def test_cloning_using_auto_now_field_is_updated(self):
time.sleep(1)
new_name = "My New Book"
clone = instance.make_clone(attrs={"name": new_name})
clone.refresh_from_db()

self.assertEqual(instance.name, name)
self.assertEqual(clone.created_by, instance.created_by)
Expand Down Expand Up @@ -227,6 +240,7 @@ def test_cloning_without_explicit_clone_m2m_fields(self):
book.authors.set([author_1, author_2])

book_clone = book.make_clone()
book_clone.refresh_from_db()

self.assertEqual(book.name, name)
self.assertEqual(book.created_by, book_clone.created_by)
Expand All @@ -238,6 +252,7 @@ def test_cloning_without_explicit_clone_m2m_fields(self):
def test_cloning_with_unique_constraint_is_valid(self):
sale_tag = SaleTag.objects.create(name="test-sale-tag")
clone_sale_tag_1 = sale_tag.make_clone()
clone_sale_tag_1.refresh_from_db()

self.assertNotEqual(sale_tag.pk, clone_sale_tag_1.pk)
self.assertRegexpMatches(
Expand All @@ -246,6 +261,7 @@ def test_cloning_with_unique_constraint_is_valid(self):
)

clone_sale_tag_2 = clone_sale_tag_1.make_clone()
clone_sale_tag_2.refresh_from_db()

self.assertNotEqual(clone_sale_tag_1.pk, clone_sale_tag_2.pk)
self.assertRegexpMatches(
Expand All @@ -256,6 +272,7 @@ def test_cloning_with_unique_constraint_is_valid(self):
def test_cloning_with_unique_constraint_uses_field_default(self):
tag = Tag.objects.create(name="test-tag")
clone_tag = tag.make_clone()
clone_tag.refresh_from_db()

self.assertNotEqual(tag.pk, clone_tag.pk)
self.assertRegexpMatches(
Expand Down Expand Up @@ -287,6 +304,7 @@ def test_cloning_with_explicit_clone_m2m_fields(
book_1.authors.set([author_1, author_2])

book_clone_1 = book_1.make_clone()
book_clone_1.refresh_from_db()

self.assertEqual(
list(book_1.authors.values_list("first_name", "last_name")),
Expand All @@ -305,6 +323,7 @@ def test_cloning_with_explicit_clone_m2m_fields(
BookTag.objects.create(book=book_2, tag=tag_2)

book_clone_2 = book_2.make_clone()
book_clone_2.refresh_from_db()

self.assertEqual(
list(book_2.tags.values_list("name")),
Expand All @@ -323,6 +342,7 @@ def test_cloning_with_explicit_clone_m2m_fields(
BookSaleTag.objects.create(book=book_3, sale_tag=sale_tag_2)

book_clone_3 = book_3.make_clone()
book_clone_3.refresh_from_db()

self.assertEqual(
list(book_3.sale_tags.values_list("name")),
Expand All @@ -340,6 +360,7 @@ def test_cloning_with_clone_excluded_fields(
_clone_excluded_fields_mock.return_value = ["last_name"]

author_clone = author.make_clone()
author_clone.refresh_from_db()

self.assertNotEqual(author.last_name, author_clone.last_name)

Expand All @@ -363,6 +384,7 @@ def test_cloning_with_explicit_related_clone_m2m_fields(
author.books.set([book_1, book_2])

author_clone = author.make_clone()
author_clone.refresh_from_db()

self.assertEqual(
list(author.books.values_list("name")),
Expand All @@ -381,6 +403,7 @@ def test_cloning_unique_fields_is_valid(self):
)

author_clone = author.make_clone()
author_clone.refresh_from_db()

self.assertNotEqual(author.pk, author_clone.pk)
self.assertEqual(
Expand Down Expand Up @@ -427,6 +450,7 @@ def test_cloning_unique_field_with_a_custom_unique_duplicate_suffix(
)

author_clone = author.make_clone()
author_clone.refresh_from_db()

self.assertNotEqual(author.pk, author_clone.pk)
self.assertEqual(
Expand All @@ -447,6 +471,7 @@ def test_cloning_unique_together_fields_with_enum_field(self):
)

author_clone_1 = author.make_clone()
author_clone_1.refresh_from_db()

self.assertNotEqual(author.pk, author_clone_1.pk)
self.assertEqual(author.sex, author_clone_1.sex)
Expand All @@ -460,6 +485,7 @@ def test_cloning_unique_together_fields_with_enum_field(self):
)

author_clone_2 = author.make_clone()
author_clone_2.refresh_from_db()

self.assertNotEqual(author.pk, author_clone_2.pk)
self.assertEqual(author.sex, author_clone_2.sex)
Expand All @@ -477,6 +503,7 @@ def test_cloning_unique_together_fields_with_enum_field(self):
)

author_clone_3 = author.make_clone()
author_clone_3.refresh_from_db()

self.assertNotEqual(author.pk, author_clone_3.pk)
self.assertEqual(author.sex, author_clone_3.sex)
Expand All @@ -498,6 +525,7 @@ def test_cloning_unique_slug_field(self):
book = Book.objects.create(name=name, created_by=self.user1, slug=slugify(name))

book_clone = book.make_clone()
book_clone.refresh_from_db()

self.assertEqual(
book_clone.slug,
Expand All @@ -509,6 +537,7 @@ def test_making_sub_clones_of_a_unique_slug_field(self):
book = Book.objects.create(name=name, created_by=self.user1, slug=slugify(name))

book_clone = book.make_clone()
book_clone.refresh_from_db()

self.assertEqual(
book_clone.slug,
Expand All @@ -517,6 +546,7 @@ def test_making_sub_clones_of_a_unique_slug_field(self):

for i in range(2, 7):
book_clone = book_clone.make_clone()
book_clone.refresh_from_db()

self.assertEqual(
book_clone.slug,
Expand All @@ -542,6 +572,7 @@ def test_making_sub_clones_of_a_non_unique_slug_field_appends_copy(
use_duplicate_suffix_for_non_unique_fields_mock.return_value = True

book_clone = book.make_clone()
book_clone.refresh_from_db()

self.assertEqual(
book_clone.custom_slug,
Expand Down Expand Up @@ -570,6 +601,7 @@ def test_cloning_unique_fields_max_length(self):
)

author_clone = author.make_clone()
author_clone.refresh_from_db()

self.assertEqual(
len(author_clone.first_name),
Expand Down Expand Up @@ -685,6 +717,7 @@ def test_cloning_one_to_many(
self.assertEqual(self.user1.book_set.count(), 1)

book_clone = book.make_clone()
book_clone.refresh_from_db()

self.assertEqual(book.name, name)
self.assertEqual(book_clone.name, name)
Expand Down Expand Up @@ -717,6 +750,7 @@ def test_cloning_many_to_one(

book.page_set.set([page])
edition_clone = edition.make_clone()
edition_clone.refresh_from_db()

self.assertNotEqual(edition.book.id, edition_clone.book.id)
self.assertEqual(edition.book.name, edition_clone.book.name)
Expand Down Expand Up @@ -745,6 +779,7 @@ def test_cloning_complex_model_relationships(self):
Furniture.objects.create(name="Chair for room 2", room=room_2)

clone_house = house.make_clone()
clone_house.refresh_from_db()

self.assertEqual(house.name, clone_house.name)
self.assertEqual(house.rooms.count(), clone_house.rooms.count())
Expand Down Expand Up @@ -960,6 +995,7 @@ def test_cloning_multiple_instances_with_autocommit_is_valid(self):
def test_cloning_model_with_unique_text_field(self):
product = Product.objects.create(name="Test Product")
clone = product.make_clone()
clone.refresh_from_db()
self.assertEqual(
clone.name,
"{0} {1} 1".format(product.name, Product.UNIQUE_DUPLICATE_SUFFIX),
Expand Down