Opened 10 years ago
Last modified 10 years ago
#23581 closed Cleanup/optimization
Changing model field choices results in spurious migrations — at Version 1
Reported by: | John-Scott Atlakson | Owned by: | nobody |
---|---|---|---|
Component: | Migrations | Version: | 1.7 |
Severity: | Release blocker | Keywords: | |
Cc: | Andrew Godwin, Iacopo Spalletti, Shai Berger | Triage Stage: | Accepted |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description (last modified by )
Consider a simple model:
from django.db import models CHOICES = ( ('1', '1'), ) class BasicModel(models.Model): choices = models.CharField(choices=CHOICES, max_length=100)
If CHOICES is changed e.g. CHOICES += (('2', '2'),), then makemigrations
insists on creating a new migration for this change. However, the migration appears to mostly be a no-op. sqlmigrate
on PostgreSQL shows:
BEGIN; ALTER TABLE "core_basicmodel" ALTER COLUMN "choices" DROP DEFAULT; COMMIT;
Which is slightly strange since the initial migration never set a DEFAULT, so there is nothing to DROP.
I first noticed this working with django-cms (see https://github.com/divio/django-cms/issues/3479). In some cases when I attempt to make a migration for an unrelated app, makemigrations
will forcefully create a migration for the cms
app because the settings.CMS_TEMPLATES choices have changed. It then makes this automatically created migration (which is output in the virtualenv e.g. env/src/django-cms/cms/migrations_django
) a dependency for the migration I actually intended to create. There doesn't appear to be a way to avoid this. This means I now have a migration I actually need for one of my apps that is completely dependent on me creating a migration for a third party app, which I don't directly control, resulting in migrations that are broken for other developers.
This can also happen when the choices differ in development vs deployment, Django will complain:
Your models have changes that are not yet reflected in a migration, and so won't be applied. Run 'manage.py makemigrations' to make new migrations, and then re-run 'manage.py migrate' to apply them.
So far this seems to mostly be harmless if slightly confusing/annoying. I am not familiar with the migration internals, but since 'choices' isn't used (at least not on PostgreSQL) to make any actual alterations to the database shouldn't it ignore this attribute?