In the example below, I am adding a new `Author` model, a field to this
model and a `unique_together` constraint for this field.
{{{#!diff
from django.db import models
+class Author(models.Model):
+ name = models.CharField(max_length=255)
+
class Book(models.Model):
name = models.CharField(max_length=255)
+ author = models.ForeignKey(Author, null=True)
+ class Meta:
+ unique_together = (
+ ('name', 'author'),
+ )
}}}
Django's migrations framework produces the following summary output:
{{{
Migrations for 'testapp':
0002_auto_20151013_1354.py:
- Create model Author
- Alter unique_together for book (1 constraint(s))
- Add field author to book
}}}
Here's the relevant portion of the migrations file:
{{{#!python
operations = [
migrations.CreateModel(
name='Author',
fields=[
('id', models.AutoField(verbose_name='ID',
serialize=False, auto_created=True, primary_key=True)),
('name', models.CharField(max_length=255)),
],
),
migrations.AlterUniqueTogether(
name='book',
unique_together=set([('name', 'author')]),
),
migrations.AddField(
model_name='book',
name='author',
field=models.ForeignKey(to='testapp.Author', null=True),
),
]
}}}
This migration fails with the following stacktrace:
{{{
Operations to perform:
Apply all migrations: testapp
Running migrations:
Rendering model states... DONE
Applying testapp.0002_auto_20151013_1354...Traceback (most recent call
last):
File "./manage.py", line 10, in <module>
execute_from_command_line(sys.argv)
File "/home/vagrant/testunique-env/local/lib/python2.7/site-
packages/django/core/management/__init__.py", line 351, in
execute_from_command_line
utility.execute()
File "/home/vagrant/testunique-env/local/lib/python2.7/site-
packages/django/core/management/__init__.py", line 343, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/home/vagrant/testunique-env/local/lib/python2.7/site-
packages/django/core/management/base.py", line 394, in run_from_argv
self.execute(*args, **cmd_options)
File "/home/vagrant/testunique-env/local/lib/python2.7/site-
packages/django/core/management/base.py", line 445, in execute
output = self.handle(*args, **options)
File "/home/vagrant/testunique-env/local/lib/python2.7/site-
packages/django/core/management/commands/migrate.py", line 222, in handle
executor.migrate(targets, plan, fake=fake, fake_initial=fake_initial)
File "/home/vagrant/testunique-env/local/lib/python2.7/site-
packages/django/db/migrations/executor.py", line 110, in migrate
self.apply_migration(states[migration], migration, fake=fake,
fake_initial=fake_initial)
File "/home/vagrant/testunique-env/local/lib/python2.7/site-
packages/django/db/migrations/executor.py", line 148, in apply_migration
state = migration.apply(state, schema_editor)
File "/home/vagrant/testunique-env/local/lib/python2.7/site-
packages/django/db/migrations/migration.py", line 115, in apply
operation.database_forwards(self.app_label, schema_editor, old_state,
project_state)
File "/home/vagrant/testunique-env/local/lib/python2.7/site-
packages/django/db/migrations/operations/models.py", line 359, in
database_forwards
getattr(new_model._meta, self.option_name, set()),
File "/home/vagrant/testunique-env/local/lib/python2.7/site-
packages/django/db/backends/sqlite3/schema.py", line 219, in
alter_unique_together
self._remake_table(model, override_uniques=new_unique_together)
File "/home/vagrant/testunique-env/local/lib/python2.7/site-
packages/django/db/backends/sqlite3/schema.py", line 140, in _remake_table
self.create_model(temp_model)
File "/home/vagrant/testunique-env/local/lib/python2.7/site-
packages/django/db/backends/base/schema.py", line 272, in create_model
columns = [model._meta.get_field(field).column for field in fields]
File "/home/vagrant/testunique-env/local/lib/python2.7/site-
packages/django/db/models/options.py", line 554, in get_field
raise FieldDoesNotExist('%s has no field named %r' %
(self.object_name, field_name))
django.core.exceptions.FieldDoesNotExist: Book has no field named
u'author'
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/25551>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
* needs_better_patch: => 0
* needs_docs: => 0
* needs_tests: => 0
* stage: Unreviewed => Accepted
Comment:
Seems similar to #22035 but I can reproduce the issue on master.
--
Ticket URL: <https://code.djangoproject.com/ticket/25551#comment:1>
* status: new => assigned
* owner: nobody => avojnovicDk
--
Ticket URL: <https://code.djangoproject.com/ticket/25551#comment:2>
* has_patch: 0 => 1
Comment:
This happens for the very specific edge case: If you create a model, make
migrations for that model, and then add a foreign key to another model
that didn't exist previously with unique together, the order of the action
in the new migration will not be correct: it will try to alter unique
together and then add the field used in unique together.
I made PR with fix for this.
--
Ticket URL: <https://code.djangoproject.com/ticket/25551#comment:3>
* needs_better_patch: 0 => 1
--
Ticket URL: <https://code.djangoproject.com/ticket/25551#comment:4>
* needs_better_patch: 1 => 0
--
Ticket URL: <https://code.djangoproject.com/ticket/25551#comment:5>
* status: assigned => closed
* resolution: => fixed
Comment:
In [changeset:"73a6ab6382809d5452907dcff5767403d8d66985" 73a6ab63]:
{{{
#!CommitTicketReference repository=""
revision="73a6ab6382809d5452907dcff5767403d8d66985"
Fixed #25551 -- Fixed migration operations ordering when adding fields and
a unique_together constraint.
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/25551#comment:6>