From 011be89e242e2b9081b61f240e60ad65686726ea Mon Sep 17 00:00:00 2001 From: Prathamesh Desai Date: Tue, 7 Jun 2022 11:02:18 +0530 Subject: [PATCH 1/6] standardize extra_fields --- .../contentcuration/utils/db_tools.py | 1 + .../contentcuration/viewsets/contentnode.py | 31 ++++++++++++++----- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/contentcuration/contentcuration/utils/db_tools.py b/contentcuration/contentcuration/utils/db_tools.py index 347f98ee00..74ddeab693 100644 --- a/contentcuration/contentcuration/utils/db_tools.py +++ b/contentcuration/contentcuration/utils/db_tools.py @@ -158,6 +158,7 @@ def create_exercise(title, parent, license_id, description="", user=None, empty= "m": 3, "n": 5, } + exercise = ContentNode.objects.create( title=title, description=description, diff --git a/contentcuration/contentcuration/viewsets/contentnode.py b/contentcuration/contentcuration/viewsets/contentnode.py index c7bb2e222a..77d7f76550 100644 --- a/contentcuration/contentcuration/viewsets/contentnode.py +++ b/contentcuration/contentcuration/viewsets/contentnode.py @@ -19,8 +19,8 @@ from django_cte import CTEQuerySet from django_filters.rest_framework import CharFilter from django_filters.rest_framework import UUIDFilter +from le_utils.constants import completion_criteria from le_utils.constants import content_kinds -from le_utils.constants import exercises from le_utils.constants import roles from le_utils.constants.labels import accessibility_categories from le_utils.constants.labels import learning_activities @@ -35,7 +35,6 @@ from rest_framework.serializers import CharField from rest_framework.serializers import ChoiceField from rest_framework.serializers import DictField -from rest_framework.serializers import IntegerField from rest_framework.serializers import ValidationError from rest_framework.viewsets import ViewSet @@ -74,6 +73,8 @@ from contentcuration.viewsets.sync.utils import generate_delete_event from contentcuration.viewsets.sync.utils import generate_update_event from contentcuration.viewsets.sync.utils import log_sync_exception +# from le_utils.constants import exercises +# from rest_framework.serializers import IntegerField channel_query = Channel.objects.filter(main_tree__tree_id=OuterRef("tree_id")) @@ -287,12 +288,7 @@ class ExtraFieldsOptionsSerializer(JSONFieldDictSerializer): class ExtraFieldsSerializer(JSONFieldDictSerializer): - mastery_model = ChoiceField( - choices=exercises.MASTERY_MODELS, allow_null=True, required=False - ) randomize = BooleanField() - m = IntegerField(allow_null=True, required=False) - n = IntegerField(allow_null=True, required=False) options = ExtraFieldsOptionsSerializer(required=False) @@ -455,6 +451,26 @@ def get_title(item): return item["title"] if item["parent_id"] else item["original_channel_name"] +def consolidate_extra_fields(item): + extra_fields = item.get("extra_fields") + if item["kind"] == content_kinds.EXERCISE: + m = extra_fields.pop("m") + n = extra_fields.pop("n") + mastery_model = extra_fields.pop("mastery_model") + if not extra_fields.get("options").get("completion_criteria"): + extra_fields["options"] = extra_fields.get("options", {}) + extra_fields["options"]["completion_criteria"] = { + "threshold": { + "m": m, + "n": n, + "mastery_model": mastery_model, + }, + "model": completion_criteria.MASTERY, + } + + return extra_fields + + class PrerequisitesUpdateHandler(ViewSet): """ Dummy viewset for handling create and delete changes for prerequisites @@ -683,6 +699,7 @@ class ContentNodeViewSet(BulkUpdateMixin, ChangeEventMixin, ValuesViewset): "accessibility_labels": partial(dict_if_none, field_name="accessibility_labels"), "categories": partial(dict_if_none, field_name="categories"), "learner_needs": partial(dict_if_none, field_name="learner_needs"), + "extra_fields": consolidate_extra_fields, } def _annotate_channel_id(self, queryset): From c7a4c2bf025a47321c6123f8d8aba2dd11669bc7 Mon Sep 17 00:00:00 2001 From: Prathamesh Desai Date: Sat, 11 Jun 2022 12:13:06 +0530 Subject: [PATCH 2/6] Tests for completion_criteria --- .../tests/viewsets/test_contentnode.py | 123 +++++++++++++++--- .../contentcuration/viewsets/contentnode.py | 17 ++- 2 files changed, 114 insertions(+), 26 deletions(-) diff --git a/contentcuration/contentcuration/tests/viewsets/test_contentnode.py b/contentcuration/contentcuration/tests/viewsets/test_contentnode.py index ef2fb9ed4b..8955f72c4c 100644 --- a/contentcuration/contentcuration/tests/viewsets/test_contentnode.py +++ b/contentcuration/contentcuration/tests/viewsets/test_contentnode.py @@ -15,6 +15,7 @@ from django_concurrent_tests.helpers import make_concurrent_calls from le_utils.constants import completion_criteria from le_utils.constants import content_kinds +from le_utils.constants import exercises from le_utils.constants import roles from le_utils.constants.labels.accessibility_categories import ACCESSIBILITYCATEGORIESLIST from le_utils.constants.labels.subjects import SUBJECTSLIST @@ -587,36 +588,113 @@ def test_cannot_update_contentnode(self): models.ContentNode.objects.get(id=contentnode.id).title, new_title ) - def test_update_contentnode_extra_fields(self): + def test_update_extra_fields_completion_criteria_set(self): user = testdata.user() - contentnode = models.ContentNode.objects.create(**self.contentnode_db_metadata) + metadata = self.contentnode_db_metadata + metadata["extra_fields"] = { + "options": { + "threshold": { + "m": 3, + "n": 6, + "mastery_model": exercises.M_OF_N, + }, + "model": completion_criteria.MASTERY, + } + } + contentnode = models.ContentNode.objects.create(**metadata) + self.client.force_authenticate(user=user) - # Update extra_fields.m - m = 5 + response = self.client.post( + self.sync_url, + [generate_update_event(contentnode.id, CONTENTNODE, { + "extra_fields.options.completion_criteria.threshold.m": 4, + "extra_fields.options.completion_criteria.threshold.n": 8, + "extra_fields.options.completion_criteria.threshold.mastery_model": exercises.M_OF_N, + "extra_fields.options.completion_criteria.model": completion_criteria.MASTERY} + )], + format="json", + ) + + self.assertEqual(response.status_code, 200, response.content) + self.assertEqual( + models.ContentNode.objects.get(id=contentnode.id).extra_fields["options"]["completion_criteria"]["threshold"]["m"], 4 + ) + self.assertEqual( + models.ContentNode.objects.get(id=contentnode.id).extra_fields["options"]["completion_criteria"]["threshold"]["n"], 8 + ) + + def test_update_extra_fields_completion_criteria_unset(self): + user = testdata.user() + metadata = self.contentnode_db_metadata + metadata["extra_fields"] = { + "m": 3, + "n": 5, + "mastery_model": exercises.M_OF_N, + } + contentnode = models.ContentNode.objects.create(**metadata) self.client.force_authenticate(user=user) + response = self.client.post( self.sync_url, - [generate_update_event(contentnode.id, CONTENTNODE, {"extra_fields.m": m})], + [generate_update_event(contentnode.id, CONTENTNODE, { + "extra_fields.options.completion_criteria.threshold.m": 4, + "extra_fields.options.completion_criteria.threshold.n": 6, + "extra_fields.options.completion_criteria.threshold.mastery_model": exercises.M_OF_N, + "extra_fields.options.completion_criteria.model": completion_criteria.MASTERY} + )], format="json", ) + self.assertEqual(response.status_code, 200, response.content) + + self.assertEqual( + models.ContentNode.objects.get(id=contentnode.id).extra_fields["m"], 3 + ) + self.assertEqual( + models.ContentNode.objects.get(id=contentnode.id).extra_fields["n"], 5 + ) + self.assertEqual( + models.ContentNode.objects.get(id=contentnode.id).extra_fields["mastery_model"], exercises.M_OF_N + ) + self.assertEqual( + models.ContentNode.objects.get(id=contentnode.id).extra_fields["options"]["completion_criteria"]["threshold"]["m"], 4 + ) + self.assertEqual( + models.ContentNode.objects.get(id=contentnode.id).extra_fields["options"]["completion_criteria"]["threshold"]["n"], 6 + ) self.assertEqual( - models.ContentNode.objects.get(id=contentnode.id).extra_fields["m"], m + models.ContentNode.objects.get(id=contentnode.id).extra_fields["options"]["completion_criteria"]["threshold"]["mastery_model"], exercises.M_OF_N ) + self.assertEqual( + models.ContentNode.objects.get(id=contentnode.id).extra_fields["options"]["completion_criteria"]["model"], completion_criteria.MASTERY + ) + + def test_update_contentnode_extra_fields(self): + user = testdata.user() + contentnode = models.ContentNode.objects.create(**self.contentnode_db_metadata) - # Update extra_fields.m + # Update m and n fields + m = 5 n = 10 + self.client.force_authenticate(user=user) + response = self.client.post( self.sync_url, - [generate_update_event(contentnode.id, CONTENTNODE, {"extra_fields.n": n})], + [generate_update_event(contentnode.id, CONTENTNODE, { + "extra_fields.options.completion_criteria.threshold.m": m, + "extra_fields.options.completion_criteria.threshold.n": n, + "extra_fields.options.completion_criteria.threshold.mastery_model": exercises.M_OF_N, + "extra_fields.options.completion_criteria.model": completion_criteria.MASTERY} + )], format="json", ) + self.assertEqual(response.status_code, 200, response.content) self.assertEqual( - models.ContentNode.objects.get(id=contentnode.id).extra_fields["m"], m + models.ContentNode.objects.get(id=contentnode.id).extra_fields["options"]["completion_criteria"]["threshold"]["m"], m ) self.assertEqual( - models.ContentNode.objects.get(id=contentnode.id).extra_fields["n"], n + models.ContentNode.objects.get(id=contentnode.id).extra_fields["options"]["completion_criteria"]["threshold"]["n"], n ) # Update extra_fields.randomize @@ -628,10 +706,10 @@ def test_update_contentnode_extra_fields(self): ) self.assertEqual(response.status_code, 200, response.content) self.assertEqual( - models.ContentNode.objects.get(id=contentnode.id).extra_fields["m"], m + models.ContentNode.objects.get(id=contentnode.id).extra_fields["options"]["completion_criteria"]["threshold"]["m"], m ) self.assertEqual( - models.ContentNode.objects.get(id=contentnode.id).extra_fields["n"], n + models.ContentNode.objects.get(id=contentnode.id).extra_fields["options"]["completion_criteria"]["threshold"]["n"], n ) self.assertEqual( models.ContentNode.objects.get(id=contentnode.id).extra_fields["randomize"], randomize @@ -641,19 +719,30 @@ def test_update_contentnode_remove_from_extra_fields(self): user = testdata.user() metadata = self.contentnode_db_metadata metadata["extra_fields"] = { - "m": 5, + "options": { + "threshold": { + "m": 5, + "n": None, + "mastery_model": exercises.M_OF_N, + }, + "model": completion_criteria.MASTERY, + } } contentnode = models.ContentNode.objects.create(**metadata) self.client.force_authenticate(user=user) - # Remove extra_fields.m + # Remove m from extra_fields response = self.client.post( self.sync_url, - [generate_update_event(contentnode.id, CONTENTNODE, {"extra_fields.m": None})], + [generate_update_event(contentnode.id, CONTENTNODE, { + "extra_fields.options.completion_criteria.threshold.m": None, + "extra_fields.options.completion_criteria.threshold.n": None, + "extra_fields.options.completion_criteria.threshold.mastery_model": exercises.M_OF_N, + "extra_fields.options.completion_criteria.model": completion_criteria.MASTERY} + )], format="json", ) self.assertEqual(response.status_code, 200, response.content) - with self.assertRaises(KeyError): - models.ContentNode.objects.get(id=contentnode.id).extra_fields["m"] + self.assertEqual(models.ContentNode.objects.get(id=contentnode.id).extra_fields["options"]["completion_criteria"]["threshold"]["m"], None) def test_update_contentnode_add_to_extra_fields_nested(self): user = testdata.user() diff --git a/contentcuration/contentcuration/viewsets/contentnode.py b/contentcuration/contentcuration/viewsets/contentnode.py index 77d7f76550..c0000d2eb7 100644 --- a/contentcuration/contentcuration/viewsets/contentnode.py +++ b/contentcuration/contentcuration/viewsets/contentnode.py @@ -35,6 +35,7 @@ from rest_framework.serializers import CharField from rest_framework.serializers import ChoiceField from rest_framework.serializers import DictField +from rest_framework.serializers import Field from rest_framework.serializers import ValidationError from rest_framework.viewsets import ViewSet @@ -73,8 +74,6 @@ from contentcuration.viewsets.sync.utils import generate_delete_event from contentcuration.viewsets.sync.utils import generate_update_event from contentcuration.viewsets.sync.utils import log_sync_exception -# from le_utils.constants import exercises -# from rest_framework.serializers import IntegerField channel_query = Channel.objects.filter(main_tree__tree_id=OuterRef("tree_id")) @@ -255,15 +254,15 @@ def update(self, queryset, all_validated_data): return all_objects -class ThresholdField(CharField): +class ThresholdField(Field): def to_representation(self, value): return value def to_internal_value(self, data): - data = super(ThresholdField, self).to_internal_value(data) try: + print(data) data = int(data) - except ValueError: + except(ValueError, TypeError): pass return data @@ -454,10 +453,10 @@ def get_title(item): def consolidate_extra_fields(item): extra_fields = item.get("extra_fields") if item["kind"] == content_kinds.EXERCISE: - m = extra_fields.pop("m") - n = extra_fields.pop("n") - mastery_model = extra_fields.pop("mastery_model") - if not extra_fields.get("options").get("completion_criteria"): + m = extra_fields.pop("m", None) + n = extra_fields.pop("n", None) + mastery_model = extra_fields.pop("mastery_model", None) + if not extra_fields.get("options", {}).get("completion_criteria", {}): extra_fields["options"] = extra_fields.get("options", {}) extra_fields["options"]["completion_criteria"] = { "threshold": { From 878fc03a6324d299c06013ff7c1fe036a61e5a43 Mon Sep 17 00:00:00 2001 From: Prathamesh Desai Date: Wed, 15 Jun 2022 00:42:25 +0530 Subject: [PATCH 3/6] added proper tests for completion_criteria --- .../tests/viewsets/test_contentnode.py | 114 +++++------------- .../contentcuration/viewsets/contentnode.py | 6 +- 2 files changed, 36 insertions(+), 84 deletions(-) diff --git a/contentcuration/contentcuration/tests/viewsets/test_contentnode.py b/contentcuration/contentcuration/tests/viewsets/test_contentnode.py index 8955f72c4c..d9a1520c46 100644 --- a/contentcuration/contentcuration/tests/viewsets/test_contentnode.py +++ b/contentcuration/contentcuration/tests/viewsets/test_contentnode.py @@ -367,6 +367,39 @@ def test_public_get_contentnode__unauthenticated(self): ) self.assertEqual(response.status_code, 403, response.content) + def test_consolidate_extra_fields(self): + + user = testdata.user() + channel = testdata.channel() + channel.public = True + channel.save() + contentnode = models.ContentNode.objects.create( + title="Aron's cool contentnode", + id=uuid.uuid4().hex, + kind_id=content_kinds.EXERCISE, + description="coolest contentnode this side of the Pacific", + parent_id=channel.main_tree_id, + extra_fields={ + "options": { + "m": 3, + "n": 6, + "mastery_model": exercises.M_OF_N, + } + } + ) + + self.client.force_authenticate(user=user) + with self.settings(TEST_ENV=False): + response = self.client.get( + self.viewset_url(pk=contentnode.id), format="json", + ) + self.assertEqual(response.status_code, 200, response.content) + print(response.data["extra_fields"]) + self.assertEqual(response.data["extra_fields"]["options"]["completion_criteria"]["threshold"]["m"], 3) + self.assertEqual(response.data["extra_fields"]["options"]["completion_criteria"]["threshold"]["n"], 6) + self.assertEqual(response.data["extra_fields"]["options"]["completion_criteria"]["threshold"]["mastery_model"], exercises.M_OF_N) + self.assertEqual(response.data["extra_fields"]["options"]["completion_criteria"]["model"], completion_criteria.MASTERY) + class SyncTestCase(StudioAPITestCase): @property @@ -588,87 +621,6 @@ def test_cannot_update_contentnode(self): models.ContentNode.objects.get(id=contentnode.id).title, new_title ) - def test_update_extra_fields_completion_criteria_set(self): - user = testdata.user() - metadata = self.contentnode_db_metadata - metadata["extra_fields"] = { - "options": { - "threshold": { - "m": 3, - "n": 6, - "mastery_model": exercises.M_OF_N, - }, - "model": completion_criteria.MASTERY, - } - } - contentnode = models.ContentNode.objects.create(**metadata) - self.client.force_authenticate(user=user) - - response = self.client.post( - self.sync_url, - [generate_update_event(contentnode.id, CONTENTNODE, { - "extra_fields.options.completion_criteria.threshold.m": 4, - "extra_fields.options.completion_criteria.threshold.n": 8, - "extra_fields.options.completion_criteria.threshold.mastery_model": exercises.M_OF_N, - "extra_fields.options.completion_criteria.model": completion_criteria.MASTERY} - )], - format="json", - ) - - self.assertEqual(response.status_code, 200, response.content) - self.assertEqual( - models.ContentNode.objects.get(id=contentnode.id).extra_fields["options"]["completion_criteria"]["threshold"]["m"], 4 - ) - self.assertEqual( - models.ContentNode.objects.get(id=contentnode.id).extra_fields["options"]["completion_criteria"]["threshold"]["n"], 8 - ) - - def test_update_extra_fields_completion_criteria_unset(self): - user = testdata.user() - metadata = self.contentnode_db_metadata - metadata["extra_fields"] = { - "m": 3, - "n": 5, - "mastery_model": exercises.M_OF_N, - } - contentnode = models.ContentNode.objects.create(**metadata) - self.client.force_authenticate(user=user) - - response = self.client.post( - self.sync_url, - [generate_update_event(contentnode.id, CONTENTNODE, { - "extra_fields.options.completion_criteria.threshold.m": 4, - "extra_fields.options.completion_criteria.threshold.n": 6, - "extra_fields.options.completion_criteria.threshold.mastery_model": exercises.M_OF_N, - "extra_fields.options.completion_criteria.model": completion_criteria.MASTERY} - )], - format="json", - ) - - self.assertEqual(response.status_code, 200, response.content) - - self.assertEqual( - models.ContentNode.objects.get(id=contentnode.id).extra_fields["m"], 3 - ) - self.assertEqual( - models.ContentNode.objects.get(id=contentnode.id).extra_fields["n"], 5 - ) - self.assertEqual( - models.ContentNode.objects.get(id=contentnode.id).extra_fields["mastery_model"], exercises.M_OF_N - ) - self.assertEqual( - models.ContentNode.objects.get(id=contentnode.id).extra_fields["options"]["completion_criteria"]["threshold"]["m"], 4 - ) - self.assertEqual( - models.ContentNode.objects.get(id=contentnode.id).extra_fields["options"]["completion_criteria"]["threshold"]["n"], 6 - ) - self.assertEqual( - models.ContentNode.objects.get(id=contentnode.id).extra_fields["options"]["completion_criteria"]["threshold"]["mastery_model"], exercises.M_OF_N - ) - self.assertEqual( - models.ContentNode.objects.get(id=contentnode.id).extra_fields["options"]["completion_criteria"]["model"], completion_criteria.MASTERY - ) - def test_update_contentnode_extra_fields(self): user = testdata.user() contentnode = models.ContentNode.objects.create(**self.contentnode_db_metadata) diff --git a/contentcuration/contentcuration/viewsets/contentnode.py b/contentcuration/contentcuration/viewsets/contentnode.py index c0000d2eb7..6221d8d6d8 100644 --- a/contentcuration/contentcuration/viewsets/contentnode.py +++ b/contentcuration/contentcuration/viewsets/contentnode.py @@ -453,9 +453,9 @@ def get_title(item): def consolidate_extra_fields(item): extra_fields = item.get("extra_fields") if item["kind"] == content_kinds.EXERCISE: - m = extra_fields.pop("m", None) - n = extra_fields.pop("n", None) - mastery_model = extra_fields.pop("mastery_model", None) + m = extra_fields.get("options", {}).pop("m", None) + n = extra_fields.get("options", {}).pop("n", None) + mastery_model = extra_fields.get("options", {}).pop("mastery_model", None) if not extra_fields.get("options", {}).get("completion_criteria", {}): extra_fields["options"] = extra_fields.get("options", {}) extra_fields["options"]["completion_criteria"] = { From 86bf229f33d538b12f33b55b6155a44ec1375250 Mon Sep 17 00:00:00 2001 From: Prathamesh Desai Date: Thu, 16 Jun 2022 20:02:46 +0530 Subject: [PATCH 4/6] removed extraneous print statement --- contentcuration/contentcuration/viewsets/contentnode.py | 1 - 1 file changed, 1 deletion(-) diff --git a/contentcuration/contentcuration/viewsets/contentnode.py b/contentcuration/contentcuration/viewsets/contentnode.py index 6221d8d6d8..e65469d06a 100644 --- a/contentcuration/contentcuration/viewsets/contentnode.py +++ b/contentcuration/contentcuration/viewsets/contentnode.py @@ -260,7 +260,6 @@ def to_representation(self, value): def to_internal_value(self, data): try: - print(data) data = int(data) except(ValueError, TypeError): pass From 41b44f868708ac72af88269dca7dc7fae49e4636 Mon Sep 17 00:00:00 2001 From: Prathamesh Desai Date: Thu, 16 Jun 2022 22:37:12 +0530 Subject: [PATCH 5/6] added extra mastrey_model condition --- .../tests/viewsets/test_contentnode.py | 29 +++++++++++++++++++ .../contentcuration/viewsets/contentnode.py | 2 +- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/contentcuration/contentcuration/tests/viewsets/test_contentnode.py b/contentcuration/contentcuration/tests/viewsets/test_contentnode.py index d9a1520c46..7106b87b55 100644 --- a/contentcuration/contentcuration/tests/viewsets/test_contentnode.py +++ b/contentcuration/contentcuration/tests/viewsets/test_contentnode.py @@ -400,6 +400,35 @@ def test_consolidate_extra_fields(self): self.assertEqual(response.data["extra_fields"]["options"]["completion_criteria"]["threshold"]["mastery_model"], exercises.M_OF_N) self.assertEqual(response.data["extra_fields"]["options"]["completion_criteria"]["model"], completion_criteria.MASTERY) + def test_consolidate_extra_fields_with_mastrey_model_none(self): + + user = testdata.user() + channel = testdata.channel() + channel.public = True + channel.save() + contentnode = models.ContentNode.objects.create( + title="Aron's cool contentnode", + id=uuid.uuid4().hex, + kind_id=content_kinds.EXERCISE, + description="coolest contentnode this side of the Pacific", + parent_id=channel.main_tree_id, + extra_fields={ + "options": { + "m": None, + "n": None, + "mastery_model": None, + } + } + ) + + self.client.force_authenticate(user=user) + with self.settings(TEST_ENV=False): + response = self.client.get( + self.viewset_url(pk=contentnode.id), format="json", + ) + self.assertEqual(response.status_code, 200, response.content) + self.assertEqual(response.data["extra_fields"]["options"], {}) + class SyncTestCase(StudioAPITestCase): @property diff --git a/contentcuration/contentcuration/viewsets/contentnode.py b/contentcuration/contentcuration/viewsets/contentnode.py index e65469d06a..62e07a221c 100644 --- a/contentcuration/contentcuration/viewsets/contentnode.py +++ b/contentcuration/contentcuration/viewsets/contentnode.py @@ -455,7 +455,7 @@ def consolidate_extra_fields(item): m = extra_fields.get("options", {}).pop("m", None) n = extra_fields.get("options", {}).pop("n", None) mastery_model = extra_fields.get("options", {}).pop("mastery_model", None) - if not extra_fields.get("options", {}).get("completion_criteria", {}): + if not extra_fields.get("options", {}).get("completion_criteria", {}) and mastery_model is not None: extra_fields["options"] = extra_fields.get("options", {}) extra_fields["options"]["completion_criteria"] = { "threshold": { From 23675f6c40050f78766241e8072202252a28d3b9 Mon Sep 17 00:00:00 2001 From: Prathamesh Desai Date: Fri, 17 Jun 2022 01:02:31 +0530 Subject: [PATCH 6/6] removed options from old format --- .../tests/viewsets/test_contentnode.py | 23 ++++++++----------- .../contentcuration/viewsets/contentnode.py | 6 ++--- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/contentcuration/contentcuration/tests/viewsets/test_contentnode.py b/contentcuration/contentcuration/tests/viewsets/test_contentnode.py index 7106b87b55..37d2ea4ec2 100644 --- a/contentcuration/contentcuration/tests/viewsets/test_contentnode.py +++ b/contentcuration/contentcuration/tests/viewsets/test_contentnode.py @@ -374,17 +374,15 @@ def test_consolidate_extra_fields(self): channel.public = True channel.save() contentnode = models.ContentNode.objects.create( - title="Aron's cool contentnode", + title="Ozer's cool contentnode", id=uuid.uuid4().hex, kind_id=content_kinds.EXERCISE, description="coolest contentnode this side of the Pacific", parent_id=channel.main_tree_id, extra_fields={ - "options": { - "m": 3, - "n": 6, - "mastery_model": exercises.M_OF_N, - } + "m": 3, + "n": 6, + "mastery_model": exercises.M_OF_N, } ) @@ -410,14 +408,13 @@ def test_consolidate_extra_fields_with_mastrey_model_none(self): title="Aron's cool contentnode", id=uuid.uuid4().hex, kind_id=content_kinds.EXERCISE, - description="coolest contentnode this side of the Pacific", + description="India is the hottest country in the world", parent_id=channel.main_tree_id, extra_fields={ - "options": { - "m": None, - "n": None, - "mastery_model": None, - } + + "m": None, + "n": None, + "mastery_model": None, } ) @@ -427,7 +424,7 @@ def test_consolidate_extra_fields_with_mastrey_model_none(self): self.viewset_url(pk=contentnode.id), format="json", ) self.assertEqual(response.status_code, 200, response.content) - self.assertEqual(response.data["extra_fields"]["options"], {}) + self.assertEqual(response.data["extra_fields"], {}) class SyncTestCase(StudioAPITestCase): diff --git a/contentcuration/contentcuration/viewsets/contentnode.py b/contentcuration/contentcuration/viewsets/contentnode.py index 62e07a221c..063212590d 100644 --- a/contentcuration/contentcuration/viewsets/contentnode.py +++ b/contentcuration/contentcuration/viewsets/contentnode.py @@ -452,9 +452,9 @@ def get_title(item): def consolidate_extra_fields(item): extra_fields = item.get("extra_fields") if item["kind"] == content_kinds.EXERCISE: - m = extra_fields.get("options", {}).pop("m", None) - n = extra_fields.get("options", {}).pop("n", None) - mastery_model = extra_fields.get("options", {}).pop("mastery_model", None) + m = extra_fields.pop("m", None) + n = extra_fields.pop("n", None) + mastery_model = extra_fields.pop("mastery_model", None) if not extra_fields.get("options", {}).get("completion_criteria", {}) and mastery_model is not None: extra_fields["options"] = extra_fields.get("options", {}) extra_fields["options"]["completion_criteria"] = {