#23101 closed Bug (fixed)
Changing name of M2MField while db_table keeps table name unchanged leads to spurious migration that changes table name
Reported by: | Owned by: | abraham.martin | |
---|---|---|---|
Component: | Migrations | Version: | 1.7-rc-2 |
Severity: | Release blocker | Keywords: | |
Cc: | Triage Stage: | Accepted | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
This is the terse version, I'm going to revisit this later as I think this and #22975 share similar root cause: using the apparent/default name and overlooking the db_table that actually sets the table's name.
In Model "Some", have a field like
x = ManyToManyField("Other") # table name app_some_x
Change that to
x_set = ManyToManyField("Other", db_table="app_some_x")
which doesn't actually change anything in the schema, but the migration sees it as a rename of the intermediate table, generates a migration, and changes the name. At this point you can observe in the shell that eg., Some.x_set.field.m2m_db_table() -> app_some_x, but the table in the database has been migrated to app_some_x_set.
(caveat: the above hasn't been tested per se, I'm summarizing to get this on record before I have to go. Marked as 1.7, but while chatting with Andrew I did check it against master - no change.)
Attachments (4)
Change History (15)
by , 10 years ago
Attachment: | models-0001.py added |
---|
by , 10 years ago
description of test results, speculation about root cause
comment:1 by , 10 years ago
Triage Stage: | Unreviewed → Accepted |
---|---|
Type: | Uncategorized → Bug |
Hi,
I cna reproduce the issue with a very simple scenario and it seems quite serious.
Using these models:
class Foo(models.Model): pass class Bar(models.Model): foos = models.ManyToManyField("Foo", db_table='custom_table')
Running manage.py makemigrations
and manage.py migrate
creates a table called <app_name>__bar_foos
instead of custom_table
.
This works fine in 1.6 so it's definitely a release blocker.
Thanks.
comment:2 by , 10 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
comment:3 by , 10 years ago
Resolution: | → fixed |
---|---|
Status: | assigned → closed |
comment:6 by , 10 years ago
Resolution: | fixed |
---|---|
Status: | closed → new |
Version: | 1.7-rc-1 → 1.7-rc-2 |
The changes in RC2 fix the initial creation, but do little or nothing for the second migration - that still such a mess that I'm not even sure how many ways it fails, though I believe the error reported is the same as ever:
OperationalError: table "x_three_ring" already exists
This is the migration from model-0001 (the initial state) to model-0002
comment:7 by , 10 years ago
I cannot replicate - running the models.py files as supplied works perfectly. Can you verify that this still fails for you on the latest master?
comment:8 by , 10 years ago
On both 1.7 RC2 and master, makemigrations and migrate run without errors.
For models One and Two it asks you if you renamed the models. But for models Three and Four, the old fields are removed and new fields are added instead of being detected as renames:
Did you rename the foo.One model to Onesie? [y/N] y Did you rename the foo.Two model to Twosies? [y/N] y Migrations for 'foo': 0002_auto_20140728_1821.py: - Rename model One to Onesie - Rename model Two to Twosies - Add field ring to four - Add field ringsies to three - Remove field ringsie from four - Remove field ring from three
This may or may not be correct, depending on how clever the rename detector is supposed to be?
comment:9 by , 10 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
comment:11 by , 10 years ago
The rename detector prefers false negatives rather than false positives, so this is expected behaviour.
However, declining or missing the rename was making django emit a CREATE then a DELETE for the fields in that order, rather than (correctly) DELETE then CREATE. I've fixed this, so at least it'll run without errors.
models-0001