Opened 2 years ago
Last modified 9 months ago
#34151 assigned Bug
Adding explicit primary key with different type doesn't update related ManyToManyFields.
Reported by: | STANISLAV LEPEKHOV | Owned by: | Akash Kumar Sen |
---|---|---|---|
Component: | Migrations | Version: | 4.1 |
Severity: | Normal | Keywords: | migrations pk uuid relation |
Cc: | Sarah Abderemane | Triage Stage: | Accepted |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description (last modified by )
Hello!
When i changed this models:
class StoreChain(models.Model): places = models.ManyToManyField(Place, blank=True) class Place(models.Model): pass
to this edition (set pk with uuid type):
class StoreChain(models.Model): uid = models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, unique=True) places = models.ManyToManyField(Place, blank=True) class Place(models.Model): uid = models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, unique=True)
Django creates a migration file that affects only the model tables, while the relationship table remains unchanged, which will cause an error, because the data type of the _ID fields in it also needs to be changed:
Change History (18)
comment:1 by , 2 years ago
Description: | modified (diff) |
---|
comment:2 by , 2 years ago
Triage Stage: | Unreviewed → Accepted |
---|
comment:3 by , 2 years ago
Easy pickings: | unset |
---|---|
Triage Stage: | Accepted → Unreviewed |
follow-up: 6 comment:4 by , 2 years ago
Component: | Core (Management commands) → Migrations |
---|---|
Summary: | django.db.migrations doesn't update *_id column data type in related table when changing pk type of linked models. → Adding explicit primary key with different type doesn't update related ManyToManyFields. |
Triage Stage: | Unreviewed → Accepted |
comment:6 by , 2 years ago
Replying to Mariusz Felisiak:
Thanks for the comments!
I wanted to note that the problem also occurs for the models.ForeignKey fields.
The migration succeeds (in the absence of links), and after adding the link, an exception is thrown.
I apologize in advance for the machine translation =)
Here is the code that will throw the exception:
class StoreChain(models.Model): places = models.ManyToManyField(Place, blank=True) class Place(models.Model): pass
if change to this edition (set pk with uuid type) and add relation after:
class StoreChain(models.Model): uid = models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, unique=True) place = models.ForeignKey (Place, blank=True, null=True) class Place(models.Model): uid = models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, unique=True)
comment:7 by , 2 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
follow-up: 9 comment:8 by , 2 years ago
Does this problem occur only while using a uuid field or even with other type fields as primary key?
comment:9 by , 2 years ago
Replying to Aravind Swaminathan:
Does this problem occur only while using a uuid field or even with other type fields as primary key?
I found an error when changing the type to UUID, I did not check with other types of fields.
comment:10 by , 2 years ago
I tried to implement a solution in a draft PR . Any input is appreciable.
follow-up: 12 comment:11 by , 21 months ago
STANISLAV, With a default uuid value you cannot insert previous values of id in the new table ? So you can only change pk to uuid field when the db is empty ? Correct me if i'm wrong.
comment:12 by , 21 months ago
Replying to Bhuvnesh:
STANISLAV, With a default uuid value you cannot insert previous values of id in the new table ? So you can only change pk to uuid field when the db is empty ? Correct me if i'm wrong.
The essence of the problem is that I cannot correctly change the DATA TYPE for the pk field (including with an empty database). If I have an integer data type and there is a m2m field in another model containing pk of these objects, then when changing the data type to uuid, there will be no changes in the m2m table after migration (the type int, int will remain there)
comment:13 by , 21 months ago
Owner: | removed |
---|---|
Status: | assigned → new |
OK, so i did some more work on this and found that it is much more complicated than i thought it would be:
- You CANNOT switch pk field type if you already have some data in it without custom operations.
- the naive solution could be to remake all the tables that are referencing to a model's pk but even that is not possible in MySql as we cannot drop a table if it is referenced by other table.(throws error in case when 2 models are related to each other)
- the only solution i can think of (and tried) is deleting all related models and then recreating them with new uid field.
So i'm deassigning myself in case someone has a better solution.
comment:14 by , 21 months ago
Owner: | set to |
---|---|
Status: | new → assigned |
comment:15 by , 19 months ago
Owner: | changed from | to
---|
comment:16 by , 19 months ago
Cc: | added |
---|
comment:17 by , 15 months ago
Owner: | removed |
---|---|
Status: | assigned → new |
comment:18 by , 9 months ago
Owner: | set to |
---|---|
Status: | new → assigned |
Thanks for the report. Please don't accept your own tickets.