#28714: Django Makemigrations don't check if field name from indexes exists on
model before creating a migration.
-------------------------------------+-------------------------------------
Reporter: Gabriel | Owner: nobody
Type: Bug | Status: new
Component: | Version: 1.11
Migrations | Keywords: indexes, migrate,
Severity: Normal | makemigrations
Triage Stage: | Has patch: 0
Unreviewed |
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
-------------------------------------+-------------------------------------
When using makemigration with indexes on class Meta in the Model Django
don't check whether the field name in fields parameter exists on Model.
Because of this both the migration files (in migrations/*.py) and the
model class on model.py will have a index that referrer to a non existing
field, so when **manage.py migrate** is run, the expection
FieldDoesNotExist will be raised, but in this moment the programmer will
have to edit both the migration file and model class to fix the error,
especially if is not possible to remove the migrations file or is more
convenient to edit the migration in projects with many Apps and many
dependency between those Apps.
Would be more convenient if makemigration before generate the new
migration files did this verification.
Example of model's code with wrong field name ("''names''") on indexes:
{{{
class ItemType(models.Model):
name = models.CharField(_('Name'), unique=True, max_length=255)
class Meta:
managed = True
db_table = 'item_type'
ordering = ['name']
indexes = [
models.Index(fields=['id'],
name='item_type_index_1'),
models.Index(fields=['-id'],
name='item_type_index_2'),
models.Index(fields=['names'],
name='item_type_index_3'),
models.Index(fields=['-names'],
name='item_type_index_4')
]
}}}
This code will not raise any exception on **makemigrations**, only the
generated code on migration file will when **migrate** is used:
{{{
migrations.AddIndex(
model_name='itemtype',
index=models.Index(fields=['names'],
name='item_type_index_3'),
),
migrations.AddIndex(
model_name='itemtype',
index=models.Index(fields=['-names'],
name='item_type_index_4'),
),
}}}
Traceback (manage.py migrate):
{{{
Traceback (most recent call last):
File "D:\Project-2015\cultural\manage.py", line 10, in <module>
execute_from_command_line(sys.argv)
File "C:\Python36\lib\site-packages\django\core\management\__init__.py",
line 364, in execute_from_command_line
utility.execute()
File "C:\Python36\lib\site-packages\django\core\management\__init__.py",
line 356, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "C:\Python36\lib\site-packages\django\core\management\base.py",
line 283, in run_from_argv
self.execute(*args, **cmd_options)
File "C:\Python36\lib\site-packages\django\core\management\base.py",
line 330, in execute
output = self.handle(*args, **options)
File "C:\Python36\lib\site-
packages\django\core\management\commands\migrate.py", line 204, in handle
fake_initial=fake_initial,
File "C:\Python36\lib\site-packages\django\db\migrations\executor.py",
line 115, in migrate
state = self._migrate_all_forwards(state, plan, full_plan, fake=fake,
fake_initial=fake_initial)
File "C:\Python36\lib\site-packages\django\db\migrations\executor.py",
line 145, in _migrate_all_forwards
state = self.apply_migration(state, migration, fake=fake,
fake_initial=fake_initial)
File "C:\Python36\lib\site-packages\django\db\migrations\executor.py",
line 244, in apply_migration
state = migration.apply(state, schema_editor)
File "C:\Python36\lib\site-packages\django\db\migrations\migration.py",
line 129, in apply
operation.database_forwards(self.app_label, schema_editor, old_state,
project_state)
File "C:\Python36\lib\site-
packages\django\db\migrations\operations\models.py", line 788, in
database_forwards
schema_editor.add_index(model, self.index)
File "C:\Python36\lib\site-packages\django\db\backends\base\schema.py",
line 331, in add_index
self.execute(index.create_sql(model, self))
File "C:\Python36\lib\site-packages\django\db\models\indexes.py", line
65, in create_sql
sql_parameters = self.get_sql_create_template_values(model,
schema_editor, using)
File "C:\Python36\lib\site-packages\django\db\models\indexes.py", line
48, in get_sql_create_template_values
fields = [model._meta.get_field(field_name) for field_name, order in
self.fields_orders]
File "C:\Python36\lib\site-packages\django\db\models\indexes.py", line
48, in <listcomp>
fields = [model._meta.get_field(field_name) for field_name, order in
self.fields_orders]
File "C:\Python36\lib\site-packages\django\db\models\options.py", line
619, in get_field
raise FieldDoesNotExist("%s has no field named '%s'" %
(self.object_name, field_name))
django.core.exceptions.FieldDoesNotExist: ItemType has no field named
'names'
}}}
Attached is this model example with a incorrect index field name that will
not raise exception on makemigration only on migrate.
This was checked on Django 1.11.5 with Python 3.6.2 on Windows 10 64bits.
To reproduce this error:
1. Add the Item App to a existing Django project
2. Run manage.py makemigrations item
3. Run manage.py migrate
--
Ticket URL: <https://code.djangoproject.com/ticket/28714>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/051.0e4051b5b2cc7d0728c44c27f46ad5fd%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.