From 1907fc9b1292a55f1b8d54f4dbcdbda16bbb36c1 Mon Sep 17 00:00:00 2001 From: shanghui Date: Fri, 1 Sep 2017 14:26:09 +0800 Subject: [PATCH] Fixed #28534 -- Made JSONField.has_changed() ignore key order and consider True/1 values as different. --- django/contrib/postgres/forms/jsonb.py | 8 ++++++++ tests/postgres_tests/test_json.py | 5 +++++ 2 files changed, 13 insertions(+) diff --git a/django/contrib/postgres/forms/jsonb.py b/django/contrib/postgres/forms/jsonb.py index 158ab8fdb9..bb681e0be3 100644 --- a/django/contrib/postgres/forms/jsonb.py +++ b/django/contrib/postgres/forms/jsonb.py @@ -52,3 +52,11 @@ class JSONField(forms.CharField): if isinstance(value, InvalidJSONInput): return value return json.dumps(value) + + def has_changed(self, initial, data): + if super().has_changed(initial, data): + return True + # For purposes of seeing whether something has changed, True isn't the + # same as 1 and the order of keys doesn't matter. + data = self.to_python(data) + return json.dumps(initial, sort_keys=True) != json.dumps(data, sort_keys=True) diff --git a/tests/postgres_tests/test_json.py b/tests/postgres_tests/test_json.py index acbd855f1a..a572e670ac 100644 --- a/tests/postgres_tests/test_json.py +++ b/tests/postgres_tests/test_json.py @@ -410,3 +410,8 @@ class TestFormField(PostgreSQLTestCase): for json_string in tests: val = field.clean(json_string) self.assertEqual(field.clean(val), val) + + def test_has_changed(self): + field = forms.JSONField() + self.assertIs(field.has_changed({'a': True}, '{"a": 1}'), True) + self.assertIs(field.has_changed({'a': 1, 'b': 2}, '{"b": 2, "a": 1}'), False)