Loading resources/models.py +15 −2 Original line number Diff line number Diff line Loading @@ -404,6 +404,10 @@ class Collection(models.Model): return int(row[0]) def descendants_resources_count(self) -> int: """ This counts resources from all the descendant collections, EXCLUDING the current collection's direct resources. """ with connection.cursor() as cursor: # For some reason, Postgresql will perform a fast index scan when given the list of collection ids as a # string literal in an ANY clause. Loading @@ -420,7 +424,7 @@ class Collection(models.Model): ) row = cursor.fetchone() if not row[0]: return self.resources.filter(deleted_at__isnull=True).count() return 0 cursor.execute( # Slow: # "select count(*) from resources_collectionmembership where collection_id = any(get_all_collection_descendants_array(%s));", Loading @@ -438,7 +442,16 @@ class Collection(models.Model): ), ) row = cursor.fetchone() return int(row[0]) + self.resources.filter(deleted_at__isnull=True).count() return int(row[0]) def descendant_resources_count(self) -> int: """ This counts descendant resources INCLUDING the current collection's direct resources. """ return ( self.descendants_resources_count() + self.resources.filter(deleted_at__isnull=True).count() ) class Meta: verbose_name = "collection" Loading rpc/methods.py +53 −1 Original line number Diff line number Diff line Loading @@ -2383,7 +2383,7 @@ def collection_stats(user: User, collection_id: int) -> dict: _check_project_permission(user, collection_instance.project, PERM_COLLECTION_READ) return { "descendants_count": collection_instance.descendants_count(), "descendants_resources_count": collection_instance.descendants_resources_count(), "descendants_resources_count": collection_instance.descendant_resources_count(), "children_count": collection_instance.children() .filter(deleted_at__isnull=True) .count(), Loading Loading @@ -2433,9 +2433,61 @@ def recycle_bin(user: User, project_id: int) -> List[Dict]: @_rpc_groups(["Resources"]) def restore_resource(user: User, resource_id: int) -> bool: """ Restore a deleted resource from the recycle bin """ pass @_rpc_groups(["Collections"]) def restore_collection(user: User, collection_id: int) -> bool: """ Restore a deleted collection from the recycle bin """ pass @_rpc_groups(["Metadatas"]) def meta_count(user: User, metadata_id: int, collection_id: int) -> dict: """ Count metadata usage. """ collection_instance = Collection.objects.filter(pk=collection_id).first() if not collection: raise ServiceException(NO_SUCH_COLLECTION) _check_project_permission(user, collection_instance.project, PERM_METADATA_READ) meta = Metadata.objects.filter(pk=metadata_id).first() if not meta: raise ServiceException(NO_SUCH_METADATA) print(meta.title) collections_ids = collection_instance.descendants_and_self_ids() return_dict = {} meta_values = ( MetadataResourceValue.objects.filter( metadata=meta, resource__collections__id__in=collections_ids ) .values("value") .distinct() ) for meta_value in meta_values: return_dict[meta_value["value"]] = MetadataResourceValue.objects.filter( metadata=meta, resource__collections__id__in=collections_ids, value=meta_value["value"], ).count() return return_dict @_rpc_groups(["Collections"]) def public_collections(user: User, project_id: int) -> List[dict]: """ Get public collections """ _check_project_permission(user, project_id, PERM_COLLECTION_READ) data = [] for col in Collection.objects.filter(public_access=True, project_id=project_id): data.append(serializers.collection(col)) return data rpc/serializers.py +0 −2 Original line number Diff line number Diff line Loading @@ -83,8 +83,6 @@ def collection( "children_count": collection_instance.children() .filter(deleted_at__isnull=True) .count(), # "descendants_count": collection_instance.descendants_count(), # "descendants_resources_count": collection_instance.descendants_resources_count(), "parent": collection_instance.parent_id, "children": None, "project_id": collection_instance.project_id, Loading rpc/tests.py +47 −1 Original line number Diff line number Diff line Loading @@ -42,7 +42,9 @@ class ServiceTestCase(TestCase): models.ProjectAccess.objects.get_or_create( project=self.test_project, user=self.test_user, role=self.admin_role ) models.ProjectAccess.objects.get_or_create( project=self.test_project, user=self.admin_user, role=self.admin_role ) # public user self.public_user = User.objects.create(username="public_user") self.public_role = models.Role.objects.create( Loading Loading @@ -142,3 +144,47 @@ class ServiceTestCase(TestCase): limit_to=2000, ) methods.simple_search(self.public_user, "pouet", self.test_project.pk) def test_descendants_resources_count(self): col = models.Collection.objects.create( title="desc col", project=self.test_project, parent=self.test_project.root_collection, ) res = models.Resource.objects.create( title="test res", ptr_project=self.test_project ) models.CollectionMembership.objects.create(collection=col, resource=res) self.assertEqual(col.descendants_resources_count(), 0) self.assertEqual(col.descendant_resources_count(), 1) def test_metas_count(self): col = models.Collection.objects.create( title="desc col", project=self.test_project, parent=self.test_project.root_collection, ) res = models.Resource.objects.create( title="test res", ptr_project=self.test_project ) models.CollectionMembership.objects.create(collection=col, resource=res) meta_set = models.MetadataSet.objects.create( project=self.test_project, title="test metadataset" ) metadata_id = methods.add_metadata( self.admin_user, "metadata test", meta_set.id ) methods.add_meta_to_resource( self.admin_user, res.pk, metadata_id, "test meta value A" ) methods.add_meta_to_resource( self.admin_user, res.pk, metadata_id, "test meta value B" ) methods.add_meta_to_resource( self.admin_user, res.pk, metadata_id, "test meta value C" ) methods.add_meta_to_resource( self.admin_user, res.pk, metadata_id, "test meta value C" ) result = methods.meta_count(self.admin_user, metadata_id, col.pk) self.assertEqual(result["test meta value C"], 1) Loading
resources/models.py +15 −2 Original line number Diff line number Diff line Loading @@ -404,6 +404,10 @@ class Collection(models.Model): return int(row[0]) def descendants_resources_count(self) -> int: """ This counts resources from all the descendant collections, EXCLUDING the current collection's direct resources. """ with connection.cursor() as cursor: # For some reason, Postgresql will perform a fast index scan when given the list of collection ids as a # string literal in an ANY clause. Loading @@ -420,7 +424,7 @@ class Collection(models.Model): ) row = cursor.fetchone() if not row[0]: return self.resources.filter(deleted_at__isnull=True).count() return 0 cursor.execute( # Slow: # "select count(*) from resources_collectionmembership where collection_id = any(get_all_collection_descendants_array(%s));", Loading @@ -438,7 +442,16 @@ class Collection(models.Model): ), ) row = cursor.fetchone() return int(row[0]) + self.resources.filter(deleted_at__isnull=True).count() return int(row[0]) def descendant_resources_count(self) -> int: """ This counts descendant resources INCLUDING the current collection's direct resources. """ return ( self.descendants_resources_count() + self.resources.filter(deleted_at__isnull=True).count() ) class Meta: verbose_name = "collection" Loading
rpc/methods.py +53 −1 Original line number Diff line number Diff line Loading @@ -2383,7 +2383,7 @@ def collection_stats(user: User, collection_id: int) -> dict: _check_project_permission(user, collection_instance.project, PERM_COLLECTION_READ) return { "descendants_count": collection_instance.descendants_count(), "descendants_resources_count": collection_instance.descendants_resources_count(), "descendants_resources_count": collection_instance.descendant_resources_count(), "children_count": collection_instance.children() .filter(deleted_at__isnull=True) .count(), Loading Loading @@ -2433,9 +2433,61 @@ def recycle_bin(user: User, project_id: int) -> List[Dict]: @_rpc_groups(["Resources"]) def restore_resource(user: User, resource_id: int) -> bool: """ Restore a deleted resource from the recycle bin """ pass @_rpc_groups(["Collections"]) def restore_collection(user: User, collection_id: int) -> bool: """ Restore a deleted collection from the recycle bin """ pass @_rpc_groups(["Metadatas"]) def meta_count(user: User, metadata_id: int, collection_id: int) -> dict: """ Count metadata usage. """ collection_instance = Collection.objects.filter(pk=collection_id).first() if not collection: raise ServiceException(NO_SUCH_COLLECTION) _check_project_permission(user, collection_instance.project, PERM_METADATA_READ) meta = Metadata.objects.filter(pk=metadata_id).first() if not meta: raise ServiceException(NO_SUCH_METADATA) print(meta.title) collections_ids = collection_instance.descendants_and_self_ids() return_dict = {} meta_values = ( MetadataResourceValue.objects.filter( metadata=meta, resource__collections__id__in=collections_ids ) .values("value") .distinct() ) for meta_value in meta_values: return_dict[meta_value["value"]] = MetadataResourceValue.objects.filter( metadata=meta, resource__collections__id__in=collections_ids, value=meta_value["value"], ).count() return return_dict @_rpc_groups(["Collections"]) def public_collections(user: User, project_id: int) -> List[dict]: """ Get public collections """ _check_project_permission(user, project_id, PERM_COLLECTION_READ) data = [] for col in Collection.objects.filter(public_access=True, project_id=project_id): data.append(serializers.collection(col)) return data
rpc/serializers.py +0 −2 Original line number Diff line number Diff line Loading @@ -83,8 +83,6 @@ def collection( "children_count": collection_instance.children() .filter(deleted_at__isnull=True) .count(), # "descendants_count": collection_instance.descendants_count(), # "descendants_resources_count": collection_instance.descendants_resources_count(), "parent": collection_instance.parent_id, "children": None, "project_id": collection_instance.project_id, Loading
rpc/tests.py +47 −1 Original line number Diff line number Diff line Loading @@ -42,7 +42,9 @@ class ServiceTestCase(TestCase): models.ProjectAccess.objects.get_or_create( project=self.test_project, user=self.test_user, role=self.admin_role ) models.ProjectAccess.objects.get_or_create( project=self.test_project, user=self.admin_user, role=self.admin_role ) # public user self.public_user = User.objects.create(username="public_user") self.public_role = models.Role.objects.create( Loading Loading @@ -142,3 +144,47 @@ class ServiceTestCase(TestCase): limit_to=2000, ) methods.simple_search(self.public_user, "pouet", self.test_project.pk) def test_descendants_resources_count(self): col = models.Collection.objects.create( title="desc col", project=self.test_project, parent=self.test_project.root_collection, ) res = models.Resource.objects.create( title="test res", ptr_project=self.test_project ) models.CollectionMembership.objects.create(collection=col, resource=res) self.assertEqual(col.descendants_resources_count(), 0) self.assertEqual(col.descendant_resources_count(), 1) def test_metas_count(self): col = models.Collection.objects.create( title="desc col", project=self.test_project, parent=self.test_project.root_collection, ) res = models.Resource.objects.create( title="test res", ptr_project=self.test_project ) models.CollectionMembership.objects.create(collection=col, resource=res) meta_set = models.MetadataSet.objects.create( project=self.test_project, title="test metadataset" ) metadata_id = methods.add_metadata( self.admin_user, "metadata test", meta_set.id ) methods.add_meta_to_resource( self.admin_user, res.pk, metadata_id, "test meta value A" ) methods.add_meta_to_resource( self.admin_user, res.pk, metadata_id, "test meta value B" ) methods.add_meta_to_resource( self.admin_user, res.pk, metadata_id, "test meta value C" ) methods.add_meta_to_resource( self.admin_user, res.pk, metadata_id, "test meta value C" ) result = methods.meta_count(self.admin_user, metadata_id, col.pk) self.assertEqual(result["test meta value C"], 1)