diff --git a/arkindex/documents/api/elements.py b/arkindex/documents/api/elements.py index 729b0b0915aafbdf6b71ae308b33c5aa8d36fccc..a3852e76c7aab6cf098611f9ae6bccf1a464c96d 100644 --- a/arkindex/documents/api/elements.py +++ b/arkindex/documents/api/elements.py @@ -1149,6 +1149,16 @@ class CorpusList(ListCreateAPIView): for c in corpora: c.access_level = corpora_level[c.id] + # Avoid making any extra queries to retrieve the top_level_type. + # We already have prefetched the types, so we can use corpus.types.all() + # when a corpus has a top_level_type_id to retrieve it. + if c.top_level_type_id is not None: + c.top_level_type = next( + element_type + for element_type in c.types.all() + if element_type.id == c.top_level_type_id + ) + return corpora diff --git a/arkindex/documents/tests/test_corpus.py b/arkindex/documents/tests/test_corpus.py index 7308792ff597e1f3a318ba87ea5cfa16c12a43aa..273470120d6c99b1722f4f47b09344ca0c887206 100644 --- a/arkindex/documents/tests/test_corpus.py +++ b/arkindex/documents/tests/test_corpus.py @@ -69,8 +69,9 @@ class TestCorpus(FixtureAPITestCase): def test_anon(self): # An anonymous user has only access to public - response = self.client.get(reverse('api:corpus')) - self.assertEqual(response.status_code, status.HTTP_200_OK) + with self.assertNumQueries(4): + response = self.client.get(reverse('api:corpus')) + self.assertEqual(response.status_code, status.HTTP_200_OK) data = response.json() self.assertEqual(len(data), 1) @@ -102,8 +103,9 @@ class TestCorpus(FixtureAPITestCase): def test_user(self): # A normal user has access to public + its private self.client.force_login(self.user) - response = self.client.get(reverse('api:corpus')) - self.assertEqual(response.status_code, status.HTTP_200_OK) + with self.assertNumQueries(7): + response = self.client.get(reverse('api:corpus')) + self.assertEqual(response.status_code, status.HTTP_200_OK) data = response.json() self.assertEqual(len(data), 2) @@ -150,7 +152,7 @@ class TestCorpus(FixtureAPITestCase): self.client.force_login(self.superuser) with self.assertNumQueries(5): response = self.client.get(reverse('api:corpus')) - self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(response.status_code, status.HTTP_200_OK) data = response.json() self.assertEqual(len(data), 3) @@ -206,6 +208,26 @@ class TestCorpus(FixtureAPITestCase): ] ) + def test_top_level_type_queries(self): + """ + Multiple corpora with top-level types should only cause one extra SQL query + """ + # Create a bunch of corpora with top-level types + for i in range(10): + corpus = Corpus.objects.create(name=str(i)) + element_type = corpus.types.create(slug='top_level') + corpus.top_level_type = element_type + corpus.save() + + self.client.force_login(self.superuser) + with self.assertNumQueries(6): + response = self.client.get(reverse('api:corpus')) + self.assertEqual(response.status_code, status.HTTP_200_OK) + data = response.json() + + self.assertEqual(len(data), 13) + self.assertSetEqual({corpus['top_level_type'] for corpus in data}, {None, 'top_level'}) + def test_mixin(self): vol1 = Element.objects.get(name="Volume 1") vol2 = Element.objects.get(name="Volume 2")