From 6b2f88e389144f026430d5db4f10554626554984 Mon Sep 17 00:00:00 2001 From: Mikko Nieminen Date: Thu, 23 Jan 2025 13:17:18 +0100 Subject: [PATCH] add ProjectSerializer children field (#1552) --- CHANGELOG.rst | 1 + docs/source/app_projectroles_api_rest.rst | 2 ++ docs/source/major_changes.rst | 1 + projectroles/serializers.py | 17 ++++++++++++++++- projectroles/tests/test_views_api.py | 16 ++++++++++++++++ projectroles/views_api.py | 5 +++++ 6 files changed, 41 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 42b7331c..4b44e97d 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -31,6 +31,7 @@ Added - Project deletion (#1090) - ``ProjectModifyPluginMixin.perform_project_delete()`` method (#1090) - ``ProjectDestroyAPIView`` REST API view (#1090) + - ``ProjectSerializer`` ``children`` field (#1552) Changed ------- diff --git a/docs/source/app_projectroles_api_rest.rst b/docs/source/app_projectroles_api_rest.rst index d0d2aa7e..bfc82ef6 100644 --- a/docs/source/app_projectroles_api_rest.rst +++ b/docs/source/app_projectroles_api_rest.rst @@ -186,5 +186,7 @@ v1.1 - ``ProjectDestroyAPIView`` * Add view +- ``ProjectRetrieveAPIView`` + * Add ``children`` field - ``RoleAssignmentOwnerTransferAPIView`` * Allow empty value for ``old_owner_role`` diff --git a/docs/source/major_changes.rst b/docs/source/major_changes.rst index e7c6a109..1989cbda 100644 --- a/docs/source/major_changes.rst +++ b/docs/source/major_changes.rst @@ -85,6 +85,7 @@ REST API View Changes * Current version: ``1.1`` (non-breaking changes) * Allowed versions: ``1.0``, ``1.1`` * ``ProjectDestroyAPIView``: Add view + * ``ProjectRetrieveAPIView``: Add ``children`` field * ``RoleAssignmentOwnerTransferAPIView``: Allow empty value for ``old_owner_role`` diff --git a/projectroles/serializers.py b/projectroles/serializers.py index b8ee6263..c63ab790 100644 --- a/projectroles/serializers.py +++ b/projectroles/serializers.py @@ -1,6 +1,7 @@ """REST API view model serializers for the projectroles app""" from email.utils import parseaddr +from packaging.version import parse as parse_version from django.conf import settings from django.contrib.auth import get_user_model @@ -374,6 +375,12 @@ class ProjectSerializer(ProjectModifyMixin, SODARModelSerializer): roles = RoleAssignmentNestedListSerializer( read_only=True, many=True, source='get_roles' ) + children = serializers.SlugRelatedField( + slug_field='sodar_uuid', + many=True, + allow_null=True, + read_only=True, + ) class Meta: model = Project @@ -388,6 +395,7 @@ class Meta: 'full_title', 'owner', 'roles', + 'children', 'sodar_uuid', ] read_only_fields = ['full_title'] @@ -566,8 +574,9 @@ def to_representation(self, instance): title=ret['title'], **{'parent__sodar_uuid': parent} if parent else {}, ) - # Return only title, full title and UUID for projects with finder role user = self.context['request'].user + + # Return only title, full title and UUID for projects with finder role if ( project.type == PROJECT_TYPE_PROJECT and project.parent @@ -583,6 +592,7 @@ def to_representation(self, instance): 'full_title': project.full_title, 'sodar_uuid': str(project.sodar_uuid), } + # Else return full serialization # Proper rendering of readme ret['readme'] = project.readme.raw or '' @@ -598,6 +608,11 @@ def to_representation(self, instance): ) # Set full_title manually ret['full_title'] = project.full_title + # Remove children field for projects and API version <1.1 + if project.type == PROJECT_TYPE_PROJECT or parse_version( + self.context['request'].version + ) < parse_version('1.1'): + ret.pop('children', None) return ret diff --git a/projectroles/tests/test_views_api.py b/projectroles/tests/test_views_api.py index d245464d..5fd252c6 100644 --- a/projectroles/tests/test_views_api.py +++ b/projectroles/tests/test_views_api.py @@ -322,6 +322,7 @@ def test_get(self): 'sodar_uuid': str(self.owner_as_cat.sodar_uuid), } }, + 'children': [str(self.project.sodar_uuid)], 'sodar_uuid': str(self.category.sodar_uuid), }, { @@ -476,6 +477,7 @@ def test_get_pagination(self): 'sodar_uuid': str(self.owner_as_cat.sodar_uuid), } }, + 'children': [str(self.project.sodar_uuid)], 'sodar_uuid': str(self.category.sodar_uuid), } ], @@ -513,6 +515,7 @@ def test_get_category(self): 'sodar_uuid': str(self.owner_as_cat.sodar_uuid), } }, + 'children': [str(self.project.sodar_uuid)], 'sodar_uuid': str(self.category.sodar_uuid), } self.assertEqual(response_data, expected) @@ -576,6 +579,17 @@ def test_get_inherited_member(self): response_data = json.loads(response.content) self.assertEqual(len(response_data['roles']), 3) + def test_get_category_v1_0(self): + """Test GET with category and API version v1.0""" + url = reverse( + 'projectroles:api_project_retrieve', + kwargs={'project': self.category.sodar_uuid}, + ) + response = self.request_knox(url, version='1.0') + self.assertEqual(response.status_code, 200) + response_data = json.loads(response.content) + self.assertNotIn('children', response_data) + class TestProjectCreateAPIView( RemoteSiteMixin, RemoteProjectMixin, ProjectrolesAPIViewTestBase @@ -999,6 +1013,7 @@ def test_put_category(self): 'sodar_uuid': str(self.category.get_owner().sodar_uuid), } }, + 'children': [str(self.project.sodar_uuid)], 'sodar_uuid': str(self.category.sodar_uuid), } self.assertEqual(json.loads(response.content), expected) @@ -1128,6 +1143,7 @@ def test_patch_category(self): 'sodar_uuid': str(self.category.get_owner().sodar_uuid), } }, + 'children': [str(self.project.sodar_uuid)], 'sodar_uuid': str(self.category.sodar_uuid), } self.assertEqual(json.loads(response.content), expected) diff --git a/projectroles/views_api.py b/projectroles/views_api.py index 2191a250..12819ee4 100644 --- a/projectroles/views_api.py +++ b/projectroles/views_api.py @@ -439,6 +439,7 @@ class ProjectRetrieveAPIView( **Returns:** - ``archive``: Project archival status (boolean) + - ``children``: Category children (list of UUIDs, only returned for categories) - ``description``: Project description (string) - ``full_title``: Full project title with parent categories (string) - ``parent``: Parent category UUID (string or null) @@ -448,6 +449,10 @@ class ProjectRetrieveAPIView( - ``sodar_uuid``: Project UUID (string) - ``title``: Project title (string) - ``type``: Project type (string, options: ``PROJECT`` or ``CATEGORY``) + + **Version Changes**: + + - ``1.1``: Add ``children`` field """ permission_required = 'projectroles.view_project'