diff --git a/django/db/migrations/state.py b/django/db/migrations/state.py index fe8594ad77..9280f5cd26 100644 --- a/django/db/migrations/state.py +++ b/django/db/migrations/state.py @@ -603,7 +603,7 @@ class ModelState: (self.name == other.name) and (len(self.fields) == len(other.fields)) and all((k1 == k2 and (f1.deconstruct()[1:] == f2.deconstruct()[1:])) - for (k1, f1), (k2, f2) in zip(self.fields, other.fields)) and + for (k1, f1), (k2, f2) in zip(sorted(self.fields), sorted(other.fields))) and (self.options == other.options) and (self.bases == other.bases) and (self.managers == other.managers) diff --git a/tests/migrations/test_state.py b/tests/migrations/test_state.py index 1bb6b66c3c..3b34376188 100644 --- a/tests/migrations/test_state.py +++ b/tests/migrations/test_state.py @@ -1042,6 +1042,28 @@ class ModelStateTests(SimpleTestCase): with self.assertRaisesMessage(InvalidBasesError, "Cannot resolve bases for []"): project_state.apps + def test_fields_ordering_equality(self): + state = ModelState( + 'migrations', + 'Tag', + [ + ('id', models.AutoField(primary_key=True)), + ('name', models.CharField(max_length=100)), + ('hidden', models.BooleanField()), + ], + ) + reordered_state = ModelState( + 'migrations', + 'Tag', + [ + ('id', models.AutoField(primary_key=True)), + # Purposedly re-ordered. + ('hidden', models.BooleanField()), + ('name', models.CharField(max_length=100)), + ], + ) + self.assertEqual(state, reordered_state) + @override_settings(TEST_SWAPPABLE_MODEL='migrations.SomeFakeModel') def test_create_swappable(self): """