Fixed #28350 -- Fixed UnboundLocalError crash in RenameField with nonexistent field.
Thanks Tim for the review.
This commit is contained in:
parent
b9f7dce84b
commit
5cbcb36839
|
@ -1,3 +1,4 @@
|
|||
from django.core.exceptions import FieldDoesNotExist
|
||||
from django.db.models.fields import NOT_PROVIDED
|
||||
from django.utils.functional import cached_property
|
||||
|
||||
|
@ -261,25 +262,27 @@ class RenameField(FieldOperation):
|
|||
)
|
||||
|
||||
def state_forwards(self, app_label, state):
|
||||
model_state = state.models[app_label, self.model_name_lower]
|
||||
# Rename the field
|
||||
state.models[app_label, self.model_name_lower].fields = [
|
||||
(self.new_name if n == self.old_name else n, f)
|
||||
for n, f in state.models[app_label, self.model_name_lower].fields
|
||||
]
|
||||
fields = model_state.fields
|
||||
for index, (name, field) in enumerate(fields):
|
||||
if name == self.old_name:
|
||||
fields[index] = (self.new_name, field)
|
||||
# Delay rendering of relationships if it's not a relational field.
|
||||
delay = not field.is_relation
|
||||
break
|
||||
else:
|
||||
raise FieldDoesNotExist(
|
||||
"%s.%s has no field named '%s'" % (app_label, self.model_name, self.old_name)
|
||||
)
|
||||
# Fix index/unique_together to refer to the new field
|
||||
options = state.models[app_label, self.model_name_lower].options
|
||||
options = model_state.options
|
||||
for option in ('index_together', 'unique_together'):
|
||||
if option in options:
|
||||
options[option] = [
|
||||
[self.new_name if n == self.old_name else n for n in together]
|
||||
for together in options[option]
|
||||
]
|
||||
for n, f in state.models[app_label, self.model_name_lower].fields:
|
||||
if n == self.new_name:
|
||||
field = f
|
||||
break
|
||||
# Delay rendering of relationships if it's not a relational field
|
||||
delay = not field.is_relation
|
||||
state.reload_model(app_label, self.model_name_lower, delay=delay)
|
||||
|
||||
def database_forwards(self, app_label, schema_editor, from_state, to_state):
|
||||
|
|
|
@ -54,3 +54,6 @@ Bugfixes
|
|||
|
||||
* Prevented a primary key alteration from adding a foreign key constraint if
|
||||
``db_constraint=False`` (:ticket:`28298`).
|
||||
|
||||
* Fixed ``UnboundLocalError`` crash in ``RenameField`` with nonexistent field
|
||||
(:ticket:`28350`).
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import unittest
|
||||
|
||||
from django.core.exceptions import FieldDoesNotExist
|
||||
from django.db import connection, migrations, models, transaction
|
||||
from django.db.migrations.migration import Migration
|
||||
from django.db.migrations.operations import CreateModel
|
||||
|
@ -1368,6 +1369,12 @@ class OperationTests(OperationTestBase):
|
|||
self.assertEqual(definition[1], [])
|
||||
self.assertEqual(definition[2], {'model_name': "Pony", 'old_name': "pink", 'new_name': "blue"})
|
||||
|
||||
def test_rename_missing_field(self):
|
||||
state = ProjectState()
|
||||
state.add_model(ModelState('app', 'model', []))
|
||||
with self.assertRaisesMessage(FieldDoesNotExist, "app.model has no field named 'field'"):
|
||||
migrations.RenameField('model', 'field', 'new_field').state_forwards('app', state)
|
||||
|
||||
def test_alter_unique_together(self):
|
||||
"""
|
||||
Tests the AlterUniqueTogether operation.
|
||||
|
|
Loading…
Reference in New Issue