From 8df6e51c732f1600fa23413e9b437bf4c2ca571c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Laur=C3=A9line=20Gu=C3=A9rin?= <zebuline@entrouvert.com>
Date: Tue, 9 Aug 2022 14:53:34 +0200
Subject: [PATCH 4/5] wcs: opti, use detail url if only one id (#68037)

---
 combo/apps/wcs/models.py | 41 +++++++++++++++++++++++++++++++++++-----
 tests/test_wcs.py        | 33 +++++++++++++++-----------------
 2 files changed, 51 insertions(+), 23 deletions(-)

diff --git a/combo/apps/wcs/models.py b/combo/apps/wcs/models.py
index 13d4ab8a..64de63bd 100644
--- a/combo/apps/wcs/models.py
+++ b/combo/apps/wcs/models.py
@@ -1087,6 +1087,10 @@ class WcsCardInfosCell(CardMixin, CellBase):
         card_ids = context.get(self.global_context_key)
         if not card_ids:
             return None
+        if len(card_ids) == 1:
+            # if only one id, do not use the list endpoint:
+            # may be url can be cached and reused by cells with related
+            return self.get_card_data(card_id=card_id, context=context)
         cards = self.get_cards_from_ids(card_ids, context)
         for card_data in cards:
             if str(card_data.get('id')) == str(card_id):
@@ -1094,8 +1098,23 @@ class WcsCardInfosCell(CardMixin, CellBase):
         return None
 
     def get_card_data(
-        self, card_slug, card_custom_view, card_id, only_for_user, without_user, context, synchronous=False
+        self,
+        card_id,
+        context,
+        card_slug=Ellipsis,
+        card_custom_view=Ellipsis,
+        only_for_user=Ellipsis,
+        without_user=Ellipsis,
+        synchronous=False,
     ):
+        if card_slug is Ellipsis:
+            card_slug = self.card_slug
+        if card_custom_view is Ellipsis:
+            card_custom_view = self.card_custom_view
+        if only_for_user is Ellipsis:
+            only_for_user = self.only_for_user
+        if without_user is Ellipsis:
+            without_user = self.without_user
         api_url = '/api/cards/%s/%s/?include-files-content=off' % (card_slug, card_id)
         if card_custom_view:
             api_url = '/api/cards/%s/%s/%s/?include-files-content=off' % (
@@ -1121,6 +1140,10 @@ class WcsCardInfosCell(CardMixin, CellBase):
             )
             response.raise_for_status()
         except RequestException:
+            if card_custom_view:
+                # if there's a custom view consider the error is a 404 because
+                # the card was not found in that view, and mark it so.
+                context['card_not_found'] = True
             return {}
 
         if response.status_code == 200:
@@ -1276,12 +1299,12 @@ class WcsCardInfosCell(CardMixin, CellBase):
                 return []
             # and data
             next_card_data = self.get_card_data(
+                card_id=card_data['fields']['%s_raw' % varname],
+                context=context,
                 card_slug=card_slug,
                 card_custom_view=None,
-                card_id=card_data['fields']['%s_raw' % varname],
                 only_for_user=False,
                 without_user=False,
-                context=context,
                 synchronous=True,
             )
             if not next_card_data:
@@ -1312,12 +1335,12 @@ class WcsCardInfosCell(CardMixin, CellBase):
             # no card id found
             return []
         card_data = self.get_card_data(
+            card_id=card_id,
+            context=context,
             card_slug=first_cell.card_slug,
             card_custom_view=first_cell.card_custom_view,
-            card_id=card_id,
             only_for_user=first_cell.only_for_user,
             without_user=first_cell.without_user,
-            context=context,
             synchronous=True,
         )
         if not card_data:
@@ -1353,6 +1376,14 @@ class WcsCardInfosCell(CardMixin, CellBase):
             elif card_ids:
                 # check that ids from related are available for user
                 # (use only_for_user and without_user flags)
+                if len(card_ids) == 1:
+                    # if only one id, do not use the list endpoint:
+                    # may be url can be cached and reused by cells with related
+                    return (
+                        card_ids
+                        if self.get_card_data(card_id=card_ids[0], context=original_context, synchronous=True)
+                        else []
+                    )
                 return self.filter_card_ids(card_ids, original_context)
 
         if self.card_ids:
diff --git a/tests/test_wcs.py b/tests/test_wcs.py
index cc468da2..a8ed6670 100644
--- a/tests/test_wcs.py
+++ b/tests/test_wcs.py
@@ -3252,8 +3252,7 @@ def test_card_cell_render_identifier(mock_send, nocache, app):
     assert 'Card Model 1' in cell_resp
     assert '<p>Unknown Card</p>' not in cell_resp
     assert len(mock_send.call_args_list) == 1
-    assert '/api/cards/card_model_1/list' in mock_send.call_args_list[0][0][0].url
-    assert '&filter-internal-id=11&' in mock_send.call_args_list[0][0][0].url
+    assert '/api/cards/card_model_1/11/' in mock_send.call_args_list[0][0][0].url
 
     # with identifiers
     page.sub_slug = ''
@@ -3271,8 +3270,7 @@ def test_card_cell_render_identifier(mock_send, nocache, app):
     assert 'Card Model 1' in cell_resp
     assert '<p>Unknown Card</p>' in cell_resp
     assert len(mock_send.call_args_list) == 1
-    assert '/api/cards/card_model_1/list' in mock_send.call_args_list[0][0][0].url
-    assert '&filter-internal-id=42&' in mock_send.call_args_list[0][0][0].url
+    assert '/api/cards/card_model_1/42/' in mock_send.call_args_list[0][0][0].url
 
     cell.card_ids = '42, , 35'
     cell.save()
@@ -3316,8 +3314,7 @@ def test_card_cell_render_identifier(mock_send, nocache, app):
     assert '/api/cards/card_model_1/list' in mock_send.call_args_list[0][0][0].url
     # cell rendering
     assert '/api/cards/card_model_1/list' in mock_send.call_args_list[1][0][0].url
-    assert '/api/cards/card_model_1/list' in mock_send.call_args_list[2][0][0].url
-    assert '&filter-internal-id=13&' in mock_send.call_args_list[2][0][0].url
+    assert '/api/cards/card_model_1/13' in mock_send.call_args_list[2][0][0].url
 
     def test_card_ids():
         mock_send.reset_mock()
@@ -3483,8 +3480,8 @@ def test_card_cell_render_identifier_from_related(mock_send, nocache, app):
             # get first cell data
             '/api/cards/card_a/1/',
             # and follow cardb relation
-            ('/api/cards/card_b/list', '&filter-internal-id=1&'),  # check user access
-            ('/api/cards/card_b/list', '&filter-internal-id=1&'),  # get card
+            '/api/cards/card_b/1/',  # check user access
+            '/api/cards/card_b/1/',  # get card
         ]
     )
     cell3.delete()  # reset
@@ -3500,8 +3497,8 @@ def test_card_cell_render_identifier_from_related(mock_send, nocache, app):
             # follow cardc relation
             '/api/cards/card_c/6/',
             # and follow cardb relation
-            ('/api/cards/card_b/list', '&filter-internal-id=7&'),  # check user access
-            ('/api/cards/card_b/list', '&filter-internal-id=7&'),  # get card
+            '/api/cards/card_b/7/',  # check user access
+            '/api/cards/card_b/7/',  # get card
         ]
     )
 
@@ -3521,8 +3518,8 @@ def test_card_cell_render_identifier_from_related(mock_send, nocache, app):
         # follow cardc relation
         '/api/cards/card_c/6/',
         # and follow cardb relation
-        ('/api/cards/card_b/list', '&filter-internal-id=7&'),  # check user access
-        ('/api/cards/card_b/list', '&filter-internal-id=7&'),  # get card
+        '/api/cards/card_b/7/',  # check user access
+        '/api/cards/card_b/7/',  # get card
     ]
     resp = app.get(page.get_online_url())
     assert len(resp.context['cells']) == 2
@@ -3558,8 +3555,8 @@ def test_card_cell_render_identifier_from_related(mock_send, nocache, app):
             # follow cardc relation
             '/api/cards/card_c/6/',
             # and follow cardb relation
-            ('/api/cards/card_b/list/a-custom-view', '&filter-internal-id=7&'),  # check user access
-            ('/api/cards/card_b/list/a-custom-view', '&filter-internal-id=7&'),  # get card
+            '/api/cards/card_b/a-custom-view/7/',  # check user access
+            '/api/cards/card_b/a-custom-view/7/',  # get card
         ]
     )
 
@@ -3877,8 +3874,8 @@ def test_card_cell_render_identifier_from_related(mock_send, nocache, app):
             # get list of card_f with cardf=42
             '/api/cards/card_f/list?orig=combo&filter-cardh=42',
             # and follow cardf reverse relation
-            ('/api/cards/card_f/list', '&filter-internal-id=41&'),  # check user access
-            ('/api/cards/card_f/list', '&filter-internal-id=41&'),  # get card
+            '/api/cards/card_f/41/',  # check user access
+            '/api/cards/card_f/41/',  # get card
         ]
     )
 
@@ -3897,8 +3894,8 @@ def test_card_cell_render_identifier_from_related(mock_send, nocache, app):
             # get list of card_g with cardf=44
             '/api/cards/card_g/list?orig=combo&filter-cardh=44',
             # and follow cardf reverse relation
-            ('/api/cards/card_g/list', '&filter-internal-id=43&'),  # check user access
-            ('/api/cards/card_g/list', '&filter-internal-id=43&'),  # get card
+            '/api/cards/card_g/43/',  # check user access
+            '/api/cards/card_g/43/',  # get card
         ]
     )
 
-- 
2.35.1

