From fcaa495d65e9cbd37f733481bda7b2d7ae9f81bf Mon Sep 17 00:00:00 2001 From: Richard Tibbles Date: Wed, 9 Aug 2023 15:58:49 -0700 Subject: [PATCH] Enhance tests and add special handling for mptt fields. --- .../kolibri_public/import_metadata_view.py | 16 +++++++++++++--- .../tests/test_importmetadata_api.py | 14 ++++++++++++-- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/contentcuration/kolibri_public/import_metadata_view.py b/contentcuration/kolibri_public/import_metadata_view.py index 9d2441e69b..534596cbb4 100644 --- a/contentcuration/kolibri_public/import_metadata_view.py +++ b/contentcuration/kolibri_public/import_metadata_view.py @@ -59,7 +59,7 @@ def _error_message(self, low): ) return error - def retrieve(self, request, pk=None): + def retrieve(self, request, pk=None): # noqa: C901 """ An endpoint to retrieve all content metadata required for importing a content node all of its ancestors, and any relevant needed metadata. @@ -139,8 +139,18 @@ def retrieve(self, request, pk=None): # Map the table name from the kolibri_public table name to the equivalent Kolibri table name table_name = kc_model._meta.db_table # Tweak our introspection here to rely on Django model meta instead of SQLAlchemy - # Read from the base_models here, as those are the ones required for this schema version - raw_fields = [field.column for field in base_model._meta.fields] + # Read valid field names from the combination of the base model, and the mptt tree fields + # of the kc_model - because the base model is abstract, it does not get the mptt fields applied + # to its meta fields attribute, so we need to read the actual fields from the kc_model, but filter + # them only to names valid for the base model. + field_names = {field.column for field in base_model._meta.fields} + if hasattr(base_model, "_mptt_meta"): + field_names.add(base_model._mptt_meta.parent_attr) + field_names.add(base_model._mptt_meta.tree_id_attr) + field_names.add(base_model._mptt_meta.left_attr) + field_names.add(base_model._mptt_meta.right_attr) + field_names.add(base_model._mptt_meta.level_attr) + raw_fields = [field.column for field in kc_model._meta.fields if field.column in field_names] if qs.model is models.Language: raw_fields = [rf for rf in raw_fields if rf != "lang_name"] + ["native_name"] qs = qs.values(*raw_fields) diff --git a/contentcuration/kolibri_public/tests/test_importmetadata_api.py b/contentcuration/kolibri_public/tests/test_importmetadata_api.py index e2da98a93b..b9184f6de1 100644 --- a/contentcuration/kolibri_public/tests/test_importmetadata_api.py +++ b/contentcuration/kolibri_public/tests/test_importmetadata_api.py @@ -5,6 +5,7 @@ from django.db.models import Q from django.urls import reverse from django.utils.http import http_date +from kolibri_content import base_models from kolibri_content import models as content from kolibri_content.constants.schema_versions import CONTENT_SCHEMA_VERSION from kolibri_public import models as public @@ -44,11 +45,20 @@ def _assert_data(self, Model, ContentModel, queryset): response = self.client.get( reverse("publicimportmetadata-detail", kwargs={"pk": self.node.id}) ) + fields = Model._meta.fields + BaseModel = getattr(base_models, Model.__name__, Model) + field_names = {field.column for field in BaseModel._meta.fields} + if hasattr(BaseModel, "_mptt_meta"): + field_names.add(BaseModel._mptt_meta.parent_attr) + field_names.add(BaseModel._mptt_meta.tree_id_attr) + field_names.add(BaseModel._mptt_meta.left_attr) + field_names.add(BaseModel._mptt_meta.right_attr) + field_names.add(BaseModel._mptt_meta.level_attr) for response_data, obj in zip(response.data[ContentModel._meta.db_table], queryset): # Ensure that we are not returning any empty objects self.assertNotEqual(response_data, {}) - for field in Model._meta.fields: - if field.column in response_data: + for field in fields: + if field.column in field_names: value = response_data[field.column] if hasattr(field, "from_db_value"): value = field.from_db_value(value, None, connection)