From 1ddaaf6a42daad71a9940cc01575ae602a167b7c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Laur=C3=A9line=20Gu=C3=A9rin?= <zebuline@entrouvert.com>
Date: Fri, 19 Feb 2021 11:18:11 +0100
Subject: [PATCH] misc: add |getlist template filter (#51184)

---
 combo/public/templatetags/combo.py | 12 ++++++++++
 tests/test_public_templatetags.py  | 35 ++++++++++++++++++++++++++++++
 tests/test_wcs_templatetags.py     | 22 ++++++++++++++++++-
 3 files changed, 68 insertions(+), 1 deletion(-)

diff --git a/combo/public/templatetags/combo.py b/combo/public/templatetags/combo.py
index 8212cb41..00f7d12a 100644
--- a/combo/public/templatetags/combo.py
+++ b/combo/public/templatetags/combo.py
@@ -314,6 +314,18 @@ def get(obj, key):
         return None
 
 
+@register.filter
+def getlist(mapping, key):
+    if mapping is None:
+        return []
+    mapping = list(mapping)
+    for value in mapping:
+        try:
+            yield value.get(key)
+        except AttributeError:
+            yield None
+
+
 @register.filter
 def split(string, separator=' '):
     return (force_text(string) or '').split(separator)
diff --git a/tests/test_public_templatetags.py b/tests/test_public_templatetags.py
index 57e53736..71fe61c1 100644
--- a/tests/test_public_templatetags.py
+++ b/tests/test_public_templatetags.py
@@ -136,6 +136,41 @@ def test_get():
     assert t.render(context) == 'hello'
 
 
+def test_getlist():
+    # nothing in context
+    t = Template('{% for v in values|getlist:"foo" %}{{ v }},{% endfor %}')
+    context = Context()
+    assert t.render(context) == ''
+    # non value
+    t = Template('{% for v in values|getlist:"foo" %}{{ v }},{% endfor %}')
+    context = Context({'values': None})
+    assert t.render(context) == ''
+    # not a list
+    t = Template('{% for v in values|getlist:"foo" %}{{ v }},{% endfor %}')
+    context = Context({'values': 'foo'})
+    assert t.render(context) == 'None,None,None,'
+    # not a list of dict
+    t = Template('{% for v in values|getlist:"foo" %}{{ v }},{% endfor %}')
+    context = Context({'values': ['foo']})
+    assert t.render(context) == 'None,'
+
+    t = Template('{% for v in values|getlist:"foo" %}{{ v }},{% endfor %}')
+    context = Context({'values': [{'foo': 'bar'}, {'foo': 'baz'}]})
+    assert t.render(context) == 'bar,baz,'
+    t = Template('{% for v in values|getlist:"unknown" %}{{ v }},{% endfor %}')
+    context = Context({'values': [{'foo': 'bar'}, {'foo': 'baz'}]})
+    assert t.render(context) == 'None,None,'
+    t = Template('{% for v in values|getlist:"k"|getlist:"v" %}{{ v }},{% endfor %}')
+    context = Context({'values': [{'k': {'v': 'bar'}}, {'k': {'v': 'baz'}}]})
+    assert t.render(context) == 'bar,baz,'
+    t = Template('{% for v in values|getlist:"k"|getlist:"unknown" %}{{ v }},{% endfor %}')
+    context = Context({'values': [{'k': {'v': 'bar'}}, {'k': {'v': 'baz'}}]})
+    assert t.render(context) == 'None,None,'
+    t = Template('{% for v in values|getlist:"k"|getlist:"v" %}{{ v }},{% endfor %}')
+    context = Context({'values': [{'k': None}, {'k': {'v': 'baz'}}]})
+    assert t.render(context) == 'None,baz,'
+
+
 def test_split():
     t = Template('{% for x in plop|split %}{{x}}<br>{% endfor %}')
     assert t.render(Context({'plop': 'ab cd ef'})) == 'ab<br>cd<br>ef<br>'
diff --git a/tests/test_wcs_templatetags.py b/tests/test_wcs_templatetags.py
index 738bda7e..94589c4f 100644
--- a/tests/test_wcs_templatetags.py
+++ b/tests/test_wcs_templatetags.py
@@ -56,7 +56,7 @@ class MockedRequestResponse(mock.Mock):
 
 
 def mocked_requests_send(request, **kwargs):
-    data = [{'id': 1}, {'id': 2}]  # fake result
+    data = [{'id': 1, 'fields': {'foo': 'bar'}}, {'id': 2, 'fields': {'foo': 'baz'}}]  # fake result
     return MockedRequestResponse(content=json.dumps({'data': data}))
 
 
@@ -311,3 +311,23 @@ def test_filter_by_status(mock_send, context, nocache):
     t = Template('{% load wcs %}{{ cards|objects:"foo"|filter_by_status:"foobar"|list }}')
     t.render(context)
     assert 'filter=foobar&' in mock_send.call_args_list[0][0][0].url
+
+
+@mock.patch('combo.apps.wcs.models.requests.send', side_effect=mocked_requests_send)
+def test_getlist(mock_send, context, nocache):
+    t = Template('{% load wcs %}{% for v in cards|objects:"foo"|getlist:"id" %}{{ v }},{% endfor %}')
+    t.render(context)
+    assert t.render(context) == "1,2,"
+    t = Template('{% load wcs %}{% for v in cards|objects:"foo"|getlist:"fields" %}{{ v }},{% endfor %}')
+    t.render(context)
+    assert t.render(context) == "{&#39;foo&#39;: &#39;bar&#39;},{&#39;foo&#39;: &#39;baz&#39;},"
+    t = Template(
+        '{% load wcs %}{% for v in cards|objects:"foo"|getlist:"fields"|getlist:"foo" %}{{ v }},{% endfor %}'
+    )
+    t.render(context)
+    assert t.render(context) == "bar,baz,"
+    t = Template(
+        '{% load wcs %}{% for v in cards|objects:"foo"|getlist:"fields"|getlist:"unknown" %}{{ v }},{% endfor %}'
+    )
+    t.render(context)
+    assert t.render(context) == "None,None,"
-- 
2.29.2

