Skip to content
Open
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
19 changes: 18 additions & 1 deletion contentcuration/kolibri_public/import_metadata_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
from rest_framework.response import Response
from rest_framework.viewsets import GenericViewSet

from contentcuration.utils.pagination import ValuesViewsetCursorPagination


def _get_kc_and_base_models(model):
try:
Expand All @@ -41,12 +43,19 @@ def _get_kc_and_base_models(model):
return kc_model, base_model


class ImportMetadataPagination(ValuesViewsetCursorPagination):
# All nodes in one request share a tree, so lft needs no id tie-break.
ordering = ("lft",)
page_size_query_param = "max_results"


# Add the standard metadata_cache decorator to this endpoint to align
# with other public endpoints
@method_decorator(metadata_cache, name="dispatch")
class ImportMetadataViewset(GenericViewSet):
# Add an explicit allow any permission class to override the Studio default
permission_classes = (AllowAny,)
pagination_class = ImportMetadataPagination
default_content_schema = CONTENT_SCHEMA_VERSION
min_content_schema = MIN_CONTENT_SCHEMA_VERSION

Expand Down Expand Up @@ -106,7 +115,13 @@ def retrieve(self, request, pk=None): # noqa: C901
# does not exist.
node = get_object_or_404(models.ContentNode.objects.all(), pk=pk)

nodes = node.get_ancestors(include_self=True)
if request.query_params.get("descendants"):
nodes = node.get_family()
else:
nodes = node.get_ancestors(include_self=True)
page = self.paginate_queryset(nodes.only("id", "lft"))
if page is not None:
nodes = page

data = {}

Expand Down Expand Up @@ -200,4 +215,6 @@ def retrieve(self, request, pk=None): # noqa: C901

data["schema_version"] = content_schema

if page is not None:
return self.get_paginated_response(data)
return Response(data)
61 changes: 61 additions & 0 deletions contentcuration/kolibri_public/tests/test_importmetadata_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
from le_utils.constants import content_kinds
from rest_framework.test import APITestCase

from contentcuration.tests.helpers import reverse_with_query


class ImportMetadataTestCase(APITestCase):
@classmethod
Expand All @@ -38,6 +40,11 @@ def setUpTestData(cls):
cls.tags = public.ContentTag.objects.filter(
id__in=cls.through_tags.values_list("contenttag_id", flat=True)
).distinct()
cls.topic = cls.node.parent
cls.ancestor_ids = list(
cls.topic.get_ancestors(include_self=True).values_list("id", flat=True)
)
cls.family_ids = list(cls.topic.get_family().values_list("id", flat=True))

def _assert_data(self, Model, ContentModel, queryset):
response = self.client.get(
Expand All @@ -64,6 +71,60 @@ def _assert_data(self, Model, ContentModel, queryset):
value = field.from_db_value(value, None, connection)
self.assertEqual(value, getattr(obj, field.column))

def _node_ids(self, data):
return [row["id"] for row in data[content.ContentNode._meta.db_table]]

def _get_topic(self, query):
return self.client.get(
reverse_with_query(
"publicimportmetadata-detail",
kwargs={"pk": self.topic.id},
query=query,
)
)

def _get_paged_node_ids(self, query):
page_size = int(query["max_results"])
node_ids = []
for _ in self.family_ids:
response = self._get_topic(query)
self.assertEqual(set(response.data), {"more", "results"})
page = response.data["results"]
page_node_ids = self._node_ids(page)
self.assertLessEqual(len(page_node_ids), page_size)
self.assertEqual(
{f["contentnode_id"] for f in page[content.File._meta.db_table]},
set(page_node_ids),
)
node_ids.extend(page_node_ids)
query = response.data["more"]
if query is None:
return node_ids
self.fail("more never became None")

def test_import_metadata_unpaginated(self):
for query, expected in (
({}, self.ancestor_ids),
({"max_results": "0"}, self.ancestor_ids),
({"max_results": "abc"}, self.ancestor_ids),
({"descendants": "true"}, self.family_ids),
):
with self.subTest(query=query):
response = self._get_topic(query)
self.assertEqual(response.status_code, 200)
self.assertEqual(self._node_ids(response.data), expected)

def test_import_metadata_paginated(self):
self.assertEqual(
self._get_paged_node_ids({"max_results": 3}), self.ancestor_ids
)

def test_import_metadata_paginated_descendants(self):
self.assertEqual(
self._get_paged_node_ids({"max_results": 2, "descendants": "true"}),
self.family_ids,
)

def test_import_metadata_nodes(self):
self._assert_data(public.ContentNode, content.ContentNode, self.all_nodes)

Expand Down
Loading