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
6 changes: 5 additions & 1 deletion contentcuration/contentcuration/db/models/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,7 @@ def _copy_tags(self, source_copy_id_map):
tag_id_map[tag.id] = new_tag.id
tags_to_create.append(new_tag)

# TODO: Can cleanup the above and change the below to use ignore_conflicts=True
ContentTag.objects.bulk_create(tags_to_create)

mappings_to_create = [
Expand All @@ -499,7 +500,10 @@ def _copy_tags(self, source_copy_id_map):
for mapping in node_tags_mappings
]

self.model.tags.through.objects.bulk_create(mappings_to_create)
# In the case that we are copying a node that is in the weird state of having a tag
# that is duplicated (with a channel tag and a null channel tag) this can cause an error
# so we ignore conflicts here to ignore the duplicate tags.
self.model.tags.through.objects.bulk_create(mappings_to_create, ignore_conflicts=True)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank goodness for ignore_conflicts!


def _copy_assessment_items(self, source_copy_id_map):
from contentcuration.models import File
Expand Down
42 changes: 37 additions & 5 deletions contentcuration/contentcuration/tests/test_contentnodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ def _check_files_for_object(source, copy):


def _check_tags_for_node(source, copy):
source_tags = source.tags.all().order_by("tag_name")
source_tags = source.tags.all().order_by("tag_name").distinct("tag_name")
copy_tags = copy.tags.all().order_by("tag_name")
assert len(source_tags) == len(copy_tags)
for source_tag, copy_tag in zip(source_tags, copy_tags):
Expand Down Expand Up @@ -415,6 +415,40 @@ def test_duplicate_nodes_with_tags(self):
num_test_tags_before, ContentTag.objects.filter(tag_name="test").count()
)

def test_duplicate_nodes_with_duplicate_tags(self):
"""
Ensures that when we copy nodes with duplicated tags they get copied
"""
new_channel = testdata.channel()

tree = TreeBuilder(tags=True)
self.channel.main_tree = tree.root
self.channel.save()

# Add a legacy tag with a set channel to test the tag copying behaviour.
legacy_tag = ContentTag.objects.create(tag_name="test", channel=self.channel)
# Add an identical tag without a set channel to make sure it gets reused.
identical_tag = ContentTag.objects.create(tag_name="test")

num_test_tags_before = ContentTag.objects.filter(tag_name="test").count()

# Add both the legacy and the new style tag and ensure that it doesn't break.
self.channel.main_tree.get_children().first().tags.add(legacy_tag)
self.channel.main_tree.get_children().first().tags.add(identical_tag)

self.channel.main_tree.copy_to(new_channel.main_tree, batch_size=1000)

_check_node_copy(
self.channel.main_tree,
new_channel.main_tree.get_children().last(),
original_channel_id=self.channel.id,
channel=new_channel,
)

self.assertEqual(
num_test_tags_before, ContentTag.objects.filter(tag_name="test").count()
)

def test_duplicate_nodes_deep(self):
"""
Ensures that when we copy nodes in a deep way, a full copy happens
Expand Down Expand Up @@ -533,8 +567,7 @@ def test_duplicate_nodes_freeze_authoring_data_no_edit(self):

def test_duplicate_nodes_no_freeze_authoring_data_edit(self):
"""
Ensures that when we copy nodes, we can exclude nodes from the descendant
hierarchy
Ensures that when we copy nodes, we can modify fields if they are not frozen for editing
"""
new_channel = testdata.channel()

Expand All @@ -553,8 +586,7 @@ def test_duplicate_nodes_no_freeze_authoring_data_edit(self):

def test_duplicate_nodes_freeze_authoring_data_edit(self):
"""
Ensures that when we copy nodes, we can exclude nodes from the descendant
hierarchy
Ensures that when we copy nodes, we can't modify fields if they are frozen for editing
"""
new_channel = testdata.channel()

Expand Down