diff --git a/django/contrib/postgres/forms/array.py b/django/contrib/postgres/forms/array.py index d16a51c2e7..2e19cd574a 100644 --- a/django/contrib/postgres/forms/array.py +++ b/django/contrib/postgres/forms/array.py @@ -221,3 +221,14 @@ class SplitArrayField(forms.Field): if errors: raise ValidationError(list(chain.from_iterable(errors))) return cleaned_data + + def has_changed(self, initial, data): + try: + data = self.to_python(data) + except ValidationError: + pass + else: + data, _ = self._remove_trailing_nulls(data) + if initial in self.empty_values and data in self.empty_values: + return False + return super().has_changed(initial, data) diff --git a/tests/postgres_tests/test_array.py b/tests/postgres_tests/test_array.py index 7686ea10a8..708852f71c 100644 --- a/tests/postgres_tests/test_array.py +++ b/tests/postgres_tests/test_array.py @@ -975,6 +975,26 @@ class TestSplitFormField(PostgreSQLSimpleTestCase): form = Form(data, instance=obj) self.assertIs(form.has_changed(), expected_result) + def test_splitarrayfield_remove_trailing_nulls_has_changed(self): + class Form(forms.ModelForm): + field = SplitArrayField(forms.IntegerField(), required=False, size=2, remove_trailing_nulls=True) + + class Meta: + model = IntegerArrayModel + fields = ('field',) + + tests = [ + ({}, {'field_0': '', 'field_1': ''}, False), + ({'field': None}, {'field_0': '', 'field_1': ''}, False), + ({'field': []}, {'field_0': '', 'field_1': ''}, False), + ({'field': [1]}, {'field_0': '1', 'field_1': ''}, False), + ] + for initial, data, expected_result in tests: + with self.subTest(initial=initial, data=data): + obj = IntegerArrayModel(**initial) + form = Form(data, instance=obj) + self.assertIs(form.has_changed(), expected_result) + class TestSplitFormWidget(PostgreSQLWidgetTestCase):