#31788: Models migration with change field foreign to many and deleting unique
together.
----------------------------+-----------------------------------------
Reporter: budzichd | Owner: David Wobrock
Type: Bug | Status: assigned
Component: Migrations | Version: 3.0
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
----------------------------+-----------------------------------------
Changes (by David Wobrock):
* cc: David Wobrock (added)
* owner: nobody => David Wobrock
* has_patch: 0 => 1
* status: new => assigned
Comment:
Quite a funny bug actually in the autodetector and how we sort migration
with respect to their dependencies.
I can't exactly reproduce the described output, but something similar.
Here is a little dive into the issue.
When changing a field from FK to M2M, the autodetector goes within
`django.db.migrations.autodetector.MigrationAutodetector.generate_altered_fields`
and creates a `RemoveField`+`AddField`, which is fine and works.
But we also generate a `AlterUniqueTogether`...
Since we call `generate_removed_altered_unique_together` before
`generate_altered_fields`, one would expect it to work as expected.
And at first, we have the right operation order: `[AlterUniqueTogether,
RemoveField, AddField]`.
However, when sorting the operations with respect to their dependencies,
we trigger the dependency that `RemoveField` should be after
`AlterUniqueTogether`.
Even if this condition is already satisfied, the `stable_topological_sort`
changes the order and returns `[AlterUniqueTogether, AddField,
RemoveField]`. The dependency is still satisfied, but our Remove/Add
became an Add/Remove, which cannot work.
In `tests/utils_tests/test_topological_sort.py`
{{{
def test_preserve_satisfied_order(self):
dependency_graph = {1: set(), 2: {1}, 3: set()}
self.assertEqual(
stable_topological_sort([1, 2, 3], dependency_graph),
[1, 2, 3],
)
}}}
return
{{{
======================================================================
FAIL: test_preserve_satisfied_order
(utils_tests.test_topological_sort.TopologicalSortTests)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/david/django/tests/utils_tests/test_topological_sort.py",
line 29, in test_preserve_satisfied_order
self.assertEqual(
AssertionError: Lists differ: [1, 3, 2] != [1, 2, 3]
First differing element 1:
3
2
- [1, 3, 2]
+ [1, 2, 3]
}}}
on my env (and since we rely on sets, I suspect that's why I don't have
the same result as described in the ticket. I think that's why Simon is
seeing a `[AddField, AlterUniqueTogether, RemoveField]`, which also
satisfies the dependencies).
(on top of that, the autodetector then optimizes the operations, and the
`AddField` followed by `RemoveField` cancel each other out, and we end up
with a single `[AlterUniqueTogether]`).
Two possible approaches to fix this:
1. Making the `AddField` depend on `RemoveField`, so that we force their
order
2. Changing the topological sort, so that it preserves the input order as
much as possible
Since the second might imply a large set of changes, so I tried
implementing the first one in this
[https://github.com/django/django/pull/15738 PR].
--
Ticket URL: <https://code.djangoproject.com/ticket/31788#comment:5>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/0107018105b881e1-04663909-0f5e-46fa-b13b-10cbc5d7779c-000000%40eu-central-1.amazonses.com.