mirror of
https://github.com/django/django.git
synced 2025-11-18 19:01:40 +00:00
Fix JSONField readonly admin display to use valid JSON
Previously, readonly JSONField values in the admin were shown as Python dicts, not valid JSON. Now, display_for_field uses json.dumps with the field's encoder to ensure correct JSON output. Fixes # (if applicable)
This commit is contained in:
parent
2e0f04507b
commit
e09564d902
2 changed files with 56 additions and 0 deletions
|
|
@ -1,5 +1,6 @@
|
|||
import datetime
|
||||
import decimal
|
||||
import json
|
||||
from collections import defaultdict
|
||||
|
||||
from django.core.exceptions import FieldDoesNotExist
|
||||
|
|
@ -398,6 +399,8 @@ def display_for_field(value, field, empty_value_display):
|
|||
return formats.number_format(value)
|
||||
elif isinstance(field, models.FileField) and value:
|
||||
return format_html('<a href="{}">{}</a>', value.url, value)
|
||||
elif isinstance(field, models.JSONField):
|
||||
return json.dumps(value, ensure_ascii=False, cls=field.encoder)
|
||||
else:
|
||||
return display_for_value(value, empty_value_display)
|
||||
|
||||
|
|
|
|||
|
|
@ -197,6 +197,59 @@ class UtilsTests(SimpleTestCase):
|
|||
display_value = display_for_field(12345, models.IntegerField(), self.empty_value)
|
||||
self.assertEqual(display_value, '12,345')
|
||||
|
||||
def test_json_display_for_field(self):
|
||||
"""
|
||||
JSONField values are displayed as valid JSON.
|
||||
"""
|
||||
tests = [
|
||||
({'foo': 'bar'}, '{"foo": "bar"}'),
|
||||
(['foo', 'bar'], '["foo", "bar"]'),
|
||||
('foo', '"foo"'),
|
||||
({'a': [1, 2]}, '{"a": [1, 2]}'),
|
||||
(None, self.empty_value),
|
||||
(True, 'true'),
|
||||
(False, 'false'),
|
||||
(123, '123'),
|
||||
(45.67, '45.67'),
|
||||
]
|
||||
for value, expected_display in tests:
|
||||
with self.subTest(value=value):
|
||||
display_value = display_for_field(value, models.JSONField(), self.empty_value)
|
||||
self.assertEqual(display_value, expected_display)
|
||||
|
||||
def test_json_display_for_field_custom_encoder(self):
|
||||
"""
|
||||
JSONField values are displayed as valid JSON with custom encoder.
|
||||
"""
|
||||
import json
|
||||
|
||||
class CustomEncoder(json.JSONEncoder):
|
||||
def default(self, obj):
|
||||
if isinstance(obj, Decimal):
|
||||
return str(obj)
|
||||
return super().default(obj)
|
||||
|
||||
field = models.JSONField(encoder=CustomEncoder)
|
||||
value = {'price': Decimal('10.50')}
|
||||
display_value = display_for_field(value, field, self.empty_value)
|
||||
# The custom encoder should convert Decimal to string
|
||||
self.assertEqual(display_value, '{"price": "10.50"}')
|
||||
|
||||
def test_json_display_for_field_unicode(self):
|
||||
"""
|
||||
JSONField values with Unicode characters are properly displayed.
|
||||
"""
|
||||
tests = [
|
||||
({'name': 'José'}, '{"name": "José"}'),
|
||||
({'emoji': '😀'}, '{"emoji": "😀"}'),
|
||||
({'chinese': '你好'}, '{"chinese": "你好"}'),
|
||||
({'mixed': 'Hello 世界 🌍'}, '{"mixed": "Hello 世界 🌍"}'),
|
||||
]
|
||||
for value, expected_display in tests:
|
||||
with self.subTest(value=value):
|
||||
display_value = display_for_field(value, models.JSONField(), self.empty_value)
|
||||
self.assertEqual(display_value, expected_display)
|
||||
|
||||
def test_list_display_for_value(self):
|
||||
display_value = display_for_value([1, 2, 3], self.empty_value)
|
||||
self.assertEqual(display_value, '1, 2, 3')
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue