Opened 10 years ago
Closed 7 years ago
#26180 closed Bug (duplicate)
Altering unique_together still sometimes missing deleted fields
| Reported by: | Julian Andrews | Owned by: | Akshesh Doshi |
|---|---|---|---|
| Component: | Migrations | Version: | 1.9 |
| Severity: | Normal | Keywords: | |
| Cc: | Triage Stage: | Accepted | |
| Has patch: | yes | Needs documentation: | yes |
| Needs tests: | yes | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
This is likely a missed edge case from #23614.
Steps to reproduce:
- Create an app
spam - Create a model
Spamclass Spam(models.Model): a = models.CharField(max_length=255) b = models.CharField(max_length=255) c = models.CharField(max_length=255) class Meta: unique_together = ( ('a', 'b'), ('b', 'c'), ) - Make migrations
- Delete field
Spam.c - Delete the second
unique_togetherconstraint (('b', 'c')) - Make migrations
- Run migrations
Output:
django.core.exceptions.FieldDoesNotExist: Spam has no field named u'c'
Note that the bug doesn't occur if no unique togther constraints remain.
Manually reversing the order of the operations in the migration (to remove the index first) produces a functional migration.
Attachments (1)
Change History (10)
comment:1 by , 10 years ago
| Triage Stage: | Unreviewed → Accepted |
|---|---|
| Type: | Uncategorized → Bug |
by , 9 years ago
| Attachment: | ticket26180-temp-fix.diff added |
|---|
comment:3 by , 9 years ago
The patch temporarily fixes the issue (attaching for anyone who gets stuck due to this bug) but some other edge cases would still get left. The actual fix would involve some changes in migrations.optimizer or the reduce methods of AlterUniqueTogether or RemoveField operations AFAICS.
comment:4 by , 9 years ago
| Has patch: | set |
|---|---|
| Owner: | changed from to |
| Status: | new → assigned |
comment:5 by , 9 years ago
| Has patch: | unset |
|---|
Unchecking "Has patch" due to "not the right approach" comment on the PR.
comment:6 by , 9 years ago
| Has patch: | set |
|---|---|
| Needs documentation: | set |
| Needs tests: | set |
An initial implementation of the suggested approach - https://github.com/django/django/pull/7038
comment:7 by , 9 years ago
comment:8 by , 8 years ago
This issue just bit me on django 1.11.4, and required a couple hours of debugging to sort out.
comment:9 by , 7 years ago
| Resolution: | → duplicate |
|---|---|
| Status: | assigned → closed |
Pretty sure this is a duplicate of #28862 as well. I'll close this one as since the other one has more context.
This is happening because the
RemoveFieldoperation is called before calling theAlterUniqueTogetheroperation, resulting in the dropping of the field before the index.In the
autodetector.py, although theRemoveFieldoperations are created before theAlterUniqueTogetheroperations but the `_sort_migrations` method corrects the order of these operations to bringAlterUniqueTogetherbeforeRemoveField. But the `_optimize_migrations` method again reverses this order inself.migrations(which is finally what is returned by the_detect_changesmethod) with no optimization as such.This change is somewhat related to https://github.com/django/django/commit/e470f311d654267ec86f9a6325ec500345b9dff2