From 8df340908bbe0b40b8eb92a68a252a64fce08acf Mon Sep 17 00:00:00 2001 From: Tim Watts Date: Fri, 3 Mar 2017 10:23:09 +0100 Subject: [PATCH] Add failing tests and fix for dict that have a key `items` #4931 (#4932) --- .../rest_framework/admin/detail.html | 2 +- .../rest_framework/admin/dict_value.html | 6 +-- .../templates/rest_framework/admin/list.html | 2 +- rest_framework/templatetags/rest_framework.py | 11 +++++ tests/test_renderers.py | 44 +++++++++++++++++++ 5 files changed, 60 insertions(+), 5 deletions(-) diff --git a/rest_framework/templates/rest_framework/admin/detail.html b/rest_framework/templates/rest_framework/admin/detail.html index 759fa163d..42cd1a36d 100644 --- a/rest_framework/templates/rest_framework/admin/detail.html +++ b/rest_framework/templates/rest_framework/admin/detail.html @@ -1,7 +1,7 @@ {% load rest_framework %} - {% for key, value in results.items %} + {% for key, value in results|items %} {% if key in details %} {% endif %} diff --git a/rest_framework/templates/rest_framework/admin/dict_value.html b/rest_framework/templates/rest_framework/admin/dict_value.html index 3392c901b..ef47b7228 100644 --- a/rest_framework/templates/rest_framework/admin/dict_value.html +++ b/rest_framework/templates/rest_framework/admin/dict_value.html @@ -1,10 +1,10 @@ {% load rest_framework %}
{{ key|capfirst }}{{ value|format_value }}
- {% for key, value in value.items %} + {% for k, v in value|items %} - - + + {% endfor %} diff --git a/rest_framework/templates/rest_framework/admin/list.html b/rest_framework/templates/rest_framework/admin/list.html index 6044ebb38..fd394d44e 100644 --- a/rest_framework/templates/rest_framework/admin/list.html +++ b/rest_framework/templates/rest_framework/admin/list.html @@ -6,7 +6,7 @@ {% for row in results %} - {% for key, value in row.items %} + {% for key, value in row|items %} {% if key in columns %} ', str(response.content)) + + def test_render_dict_with_items_key(self): + factory = APIRequestFactory() + + class DummyView(APIView): + renderer_classes = (AdminRenderer, ) + + def get(self, request): + return Response({'items': 'a string'}) + + view = DummyView.as_view() + request = factory.get('/') + response = view(request) + response.render() + self.assertInHTML('', str(response.content)) + + def test_render_dict_with_iteritems_key(self): + factory = APIRequestFactory() + + class DummyView(APIView): + renderer_classes = (AdminRenderer, ) + + def get(self, request): + return Response({'iteritems': 'a string'}) + + view = DummyView.as_view() + request = factory.get('/') + response = view(request) + response.render() + self.assertInHTML('', str(response.content))
{{ key|format_value }}{{ value|format_value }}{{ k|format_value }}{{ v|format_value }}
{{ value|format_value }} diff --git a/rest_framework/templatetags/rest_framework.py b/rest_framework/templatetags/rest_framework.py index cfba054f6..d62ac4800 100644 --- a/rest_framework/templatetags/rest_framework.py +++ b/rest_framework/templatetags/rest_framework.py @@ -163,6 +163,17 @@ def format_value(value): return six.text_type(value) +@register.filter +def items(value): + """ + Simple filter to return the items of the dict. Useful when the dict may + have a key 'items' which is resolved first in Django tempalte dot-notation + lookup. See issue #4931 + Also see: https://stackoverflow.com/questions/15416662/django-template-loop-over-dictionary-items-with-items-as-key + """ + return value.items() + + @register.filter def add_nested_class(value): if isinstance(value, dict): diff --git a/tests/test_renderers.py b/tests/test_renderers.py index eba5b8104..12ac2dfc8 100644 --- a/tests/test_renderers.py +++ b/tests/test_renderers.py @@ -648,3 +648,47 @@ class AdminRendererTests(TestCase): assert result == '' assert response.status_code == status.HTTP_303_SEE_OTHER assert response['Location'] == 'http://example.com' + + def test_render_dict(self): + factory = APIRequestFactory() + + class DummyView(APIView): + renderer_classes = (AdminRenderer, ) + + def get(self, request): + return Response({'foo': 'a string'}) + view = DummyView.as_view() + request = factory.get('/') + response = view(request) + response.render() + self.assertInHTML('
Fooa string
Itemsa string
Iteritemsa string