Refs #29898 -- Changed fields in ProjectState's relation registry to dict.
This commit is contained in:
parent
7ea86076fc
commit
fa1d7ba5b9
|
@ -483,7 +483,7 @@ class MigrationAutodetector:
|
||||||
fields = list(model_state.fields.values()) + [
|
fields = list(model_state.fields.values()) + [
|
||||||
field.remote_field
|
field.remote_field
|
||||||
for relations in self.to_state.relations[app_label, model_name].values()
|
for relations in self.to_state.relations[app_label, model_name].values()
|
||||||
for _, field in relations
|
for field in relations.values()
|
||||||
]
|
]
|
||||||
for field in fields:
|
for field in fields:
|
||||||
if field.is_relation:
|
if field.is_relation:
|
||||||
|
@ -672,7 +672,7 @@ class MigrationAutodetector:
|
||||||
if (app_label, model_name) in self.old_proxy_keys:
|
if (app_label, model_name) in self.old_proxy_keys:
|
||||||
for related_model_key, related_fields in relations[app_label, model_name].items():
|
for related_model_key, related_fields in relations[app_label, model_name].items():
|
||||||
related_model_state = self.to_state.models[related_model_key]
|
related_model_state = self.to_state.models[related_model_key]
|
||||||
for related_field_name, related_field in related_fields:
|
for related_field_name, related_field in related_fields.items():
|
||||||
self.add_operation(
|
self.add_operation(
|
||||||
related_model_state.app_label,
|
related_model_state.app_label,
|
||||||
operations.AlterField(
|
operations.AlterField(
|
||||||
|
@ -777,7 +777,7 @@ class MigrationAutodetector:
|
||||||
for (related_object_app_label, object_name), relation_related_fields in (
|
for (related_object_app_label, object_name), relation_related_fields in (
|
||||||
relations[app_label, model_name].items()
|
relations[app_label, model_name].items()
|
||||||
):
|
):
|
||||||
for field_name, field in relation_related_fields:
|
for field_name, field in relation_related_fields.items():
|
||||||
dependencies.append(
|
dependencies.append(
|
||||||
(related_object_app_label, object_name, field_name, False),
|
(related_object_app_label, object_name, field_name, False),
|
||||||
)
|
)
|
||||||
|
@ -1082,7 +1082,10 @@ class MigrationAutodetector:
|
||||||
else:
|
else:
|
||||||
relations = project_state.relations[app_label, model_name]
|
relations = project_state.relations[app_label, model_name]
|
||||||
for (remote_app_label, remote_model_name), fields in relations.items():
|
for (remote_app_label, remote_model_name), fields in relations.items():
|
||||||
if any(field == related_field.remote_field for _, related_field in fields):
|
if any(
|
||||||
|
field == related_field.remote_field
|
||||||
|
for related_field in fields.values()
|
||||||
|
):
|
||||||
remote_field_model = f'{remote_app_label}.{remote_model_name}'
|
remote_field_model = f'{remote_app_label}.{remote_model_name}'
|
||||||
break
|
break
|
||||||
# Account for FKs to swappable models
|
# Account for FKs to swappable models
|
||||||
|
|
|
@ -97,7 +97,7 @@ class ProjectState:
|
||||||
assert isinstance(real_apps, set)
|
assert isinstance(real_apps, set)
|
||||||
self.real_apps = real_apps
|
self.real_apps = real_apps
|
||||||
self.is_delayed = False
|
self.is_delayed = False
|
||||||
# {remote_model_key: {model_key: [(field_name, field)]}}
|
# {remote_model_key: {model_key: {field_name: field}}}
|
||||||
self._relations = None
|
self._relations = None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -302,14 +302,10 @@ class ProjectState:
|
||||||
old_name_lower = old_name.lower()
|
old_name_lower = old_name.lower()
|
||||||
new_name_lower = new_name.lower()
|
new_name_lower = new_name.lower()
|
||||||
for to_model in self._relations.values():
|
for to_model in self._relations.values():
|
||||||
# It's safe to modify the same collection that is iterated
|
if old_name_lower in to_model[model_key]:
|
||||||
# because `break` is called right after.
|
field = to_model[model_key].pop(old_name_lower)
|
||||||
for field_name, field in to_model[model_key]:
|
field.name = new_name_lower
|
||||||
if field_name == old_name_lower:
|
to_model[model_key][new_name_lower] = field
|
||||||
field.name = new_name_lower
|
|
||||||
to_model[model_key].remove((old_name_lower, field))
|
|
||||||
to_model[model_key].append((new_name_lower, field))
|
|
||||||
break
|
|
||||||
self.reload_model(*model_key, delay=delay)
|
self.reload_model(*model_key, delay=delay)
|
||||||
|
|
||||||
def _find_reload_model(self, app_label, model_name, delay=False):
|
def _find_reload_model(self, app_label, model_name, delay=False):
|
||||||
|
@ -406,9 +402,13 @@ class ProjectState:
|
||||||
remote_model_key = concretes[remote_model_key]
|
remote_model_key = concretes[remote_model_key]
|
||||||
relations_to_remote_model = self._relations[remote_model_key]
|
relations_to_remote_model = self._relations[remote_model_key]
|
||||||
if field_name in self.models[model_key].fields:
|
if field_name in self.models[model_key].fields:
|
||||||
relations_to_remote_model[model_key].append((field_name, field))
|
# The assert holds because it's a new relation, or an altered
|
||||||
|
# relation, in which case references have been removed by
|
||||||
|
# alter_field().
|
||||||
|
assert field_name not in relations_to_remote_model[model_key]
|
||||||
|
relations_to_remote_model[model_key][field_name] = field
|
||||||
else:
|
else:
|
||||||
relations_to_remote_model[model_key].remove((field_name, field))
|
del relations_to_remote_model[model_key][field_name]
|
||||||
if not relations_to_remote_model[model_key]:
|
if not relations_to_remote_model[model_key]:
|
||||||
del relations_to_remote_model[model_key]
|
del relations_to_remote_model[model_key]
|
||||||
|
|
||||||
|
@ -444,8 +444,8 @@ class ProjectState:
|
||||||
for field_name, field in model_state.fields.items():
|
for field_name, field in model_state.fields.items():
|
||||||
field.name = field_name
|
field.name = field_name
|
||||||
# Resolve relations.
|
# Resolve relations.
|
||||||
# {remote_model_key: {model_key: [(field_name, field)]}}
|
# {remote_model_key: {model_key: {field_name: field}}}
|
||||||
self._relations = defaultdict(partial(defaultdict, list))
|
self._relations = defaultdict(partial(defaultdict, dict))
|
||||||
concretes, proxies = self._get_concrete_models_mapping_and_proxy_models()
|
concretes, proxies = self._get_concrete_models_mapping_and_proxy_models()
|
||||||
|
|
||||||
for model_key in concretes:
|
for model_key in concretes:
|
||||||
|
|
|
@ -1216,7 +1216,7 @@ class StateRelationsTests(SimpleTestCase):
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
project_state.relations['tests', 'post']['tests', 'post'],
|
project_state.relations['tests', 'post']['tests', 'post'],
|
||||||
[('next_post', new_field)],
|
{'next_post': new_field},
|
||||||
)
|
)
|
||||||
# Add a foreign key.
|
# Add a foreign key.
|
||||||
new_field = models.ForeignKey('tests.post', models.CASCADE)
|
new_field = models.ForeignKey('tests.post', models.CASCADE)
|
||||||
|
@ -1229,7 +1229,7 @@ class StateRelationsTests(SimpleTestCase):
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
project_state.relations['tests', 'post']['tests', 'comment'],
|
project_state.relations['tests', 'post']['tests', 'comment'],
|
||||||
[('post', new_field)],
|
{'post': new_field},
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_add_field_m2m_with_through(self):
|
def test_add_field_m2m_with_through(self):
|
||||||
|
@ -1271,7 +1271,7 @@ class StateRelationsTests(SimpleTestCase):
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
project_state.relations['tests', 'tag']['tests', 'post'],
|
project_state.relations['tests', 'tag']['tests', 'post'],
|
||||||
[('tags', new_field)],
|
{'tags': new_field},
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_remove_field(self):
|
def test_remove_field(self):
|
||||||
|
@ -1308,14 +1308,14 @@ class StateRelationsTests(SimpleTestCase):
|
||||||
field = project_state.models['tests', 'comment'].fields['user']
|
field = project_state.models['tests', 'comment'].fields['user']
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
project_state.relations['tests', 'user']['tests', 'comment'],
|
project_state.relations['tests', 'user']['tests', 'comment'],
|
||||||
[('user', field)],
|
{'user': field},
|
||||||
)
|
)
|
||||||
|
|
||||||
project_state.rename_field('tests', 'comment', 'user', 'author')
|
project_state.rename_field('tests', 'comment', 'user', 'author')
|
||||||
renamed_field = project_state.models['tests', 'comment'].fields['author']
|
renamed_field = project_state.models['tests', 'comment'].fields['author']
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
project_state.relations['tests', 'user']['tests', 'comment'],
|
project_state.relations['tests', 'user']['tests', 'comment'],
|
||||||
[('author', renamed_field)],
|
{'author': renamed_field},
|
||||||
)
|
)
|
||||||
self.assertEqual(field, renamed_field)
|
self.assertEqual(field, renamed_field)
|
||||||
|
|
||||||
|
@ -1357,7 +1357,7 @@ class StateRelationsTests(SimpleTestCase):
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
project_state.relations['tests', 'user']['tests', 'comment'],
|
project_state.relations['tests', 'user']['tests', 'comment'],
|
||||||
[('user', m2m_field)],
|
{'user': m2m_field},
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_alter_field_m2m_to_fk(self):
|
def test_alter_field_m2m_to_fk(self):
|
||||||
|
@ -1387,7 +1387,7 @@ class StateRelationsTests(SimpleTestCase):
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
project_state.relations['tests_other', 'user_other']['tests', 'post'],
|
project_state.relations['tests_other', 'user_other']['tests', 'post'],
|
||||||
[('authors', foreign_key)],
|
{'authors': foreign_key},
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_many_relations_to_same_model(self):
|
def test_many_relations_to_same_model(self):
|
||||||
|
@ -1403,14 +1403,14 @@ class StateRelationsTests(SimpleTestCase):
|
||||||
comment_rels = project_state.relations['tests', 'user']['tests', 'comment']
|
comment_rels = project_state.relations['tests', 'user']['tests', 'comment']
|
||||||
# Two foreign keys to the same model.
|
# Two foreign keys to the same model.
|
||||||
self.assertEqual(len(comment_rels), 2)
|
self.assertEqual(len(comment_rels), 2)
|
||||||
self.assertEqual(comment_rels[1], ('reviewer', new_field))
|
self.assertEqual(comment_rels['reviewer'], new_field)
|
||||||
# Rename the second foreign key.
|
# Rename the second foreign key.
|
||||||
project_state.rename_field('tests', 'comment', 'reviewer', 'supervisor')
|
project_state.rename_field('tests', 'comment', 'reviewer', 'supervisor')
|
||||||
self.assertEqual(len(comment_rels), 2)
|
self.assertEqual(len(comment_rels), 2)
|
||||||
self.assertEqual(comment_rels[1], ('supervisor', new_field))
|
self.assertEqual(comment_rels['supervisor'], new_field)
|
||||||
# Remove the first foreign key.
|
# Remove the first foreign key.
|
||||||
project_state.remove_field('tests', 'comment', 'user')
|
project_state.remove_field('tests', 'comment', 'user')
|
||||||
self.assertEqual(comment_rels, [('supervisor', new_field)])
|
self.assertEqual(comment_rels, {'supervisor': new_field})
|
||||||
|
|
||||||
|
|
||||||
class ModelStateTests(SimpleTestCase):
|
class ModelStateTests(SimpleTestCase):
|
||||||
|
|
Loading…
Reference in New Issue