Refs #27666 -- Added ProjectState.reload_models().
This commit is contained in:
parent
45ded053b1
commit
46e0335583
|
@ -306,6 +306,7 @@ class RenameModel(ModelOperation):
|
||||||
# Repoint all fields pointing to the old model to the new one.
|
# Repoint all fields pointing to the old model to the new one.
|
||||||
old_model_tuple = app_label, self.old_name_lower
|
old_model_tuple = app_label, self.old_name_lower
|
||||||
new_remote_model = '%s.%s' % (app_label, self.new_name)
|
new_remote_model = '%s.%s' % (app_label, self.new_name)
|
||||||
|
to_reload = []
|
||||||
for (model_app_label, model_name), model_state in state.models.items():
|
for (model_app_label, model_name), model_state in state.models.items():
|
||||||
model_changed = False
|
model_changed = False
|
||||||
for index, (name, field) in enumerate(model_state.fields):
|
for index, (name, field) in enumerate(model_state.fields):
|
||||||
|
@ -331,7 +332,9 @@ class RenameModel(ModelOperation):
|
||||||
model_state.fields[index] = name, changed_field
|
model_state.fields[index] = name, changed_field
|
||||||
model_changed = True
|
model_changed = True
|
||||||
if model_changed:
|
if model_changed:
|
||||||
state.reload_model(model_app_label, model_name, delay=True)
|
to_reload.append((model_app_label, model_name))
|
||||||
|
# Reload models related to old model before removing the old model.
|
||||||
|
state.reload_models(to_reload, delay=True)
|
||||||
# Remove the old model.
|
# Remove the old model.
|
||||||
state.remove_model(app_label, self.old_name_lower)
|
state.remove_model(app_label, self.old_name_lower)
|
||||||
state.reload_model(app_label, self.new_name_lower, delay=True)
|
state.reload_model(app_label, self.new_name_lower, delay=True)
|
||||||
|
|
|
@ -112,75 +112,91 @@ class ProjectState(object):
|
||||||
# the cache automatically (#24513)
|
# the cache automatically (#24513)
|
||||||
self.apps.clear_cache()
|
self.apps.clear_cache()
|
||||||
|
|
||||||
def reload_model(self, app_label, model_name, delay=False):
|
def _find_reload_model(self, app_label, model_name, delay=False):
|
||||||
if delay:
|
if delay:
|
||||||
self.is_delayed = True
|
self.is_delayed = True
|
||||||
|
|
||||||
if 'apps' in self.__dict__: # hasattr would cache the property
|
related_models = set()
|
||||||
try:
|
|
||||||
old_model = self.apps.get_model(app_label, model_name)
|
try:
|
||||||
except LookupError:
|
old_model = self.apps.get_model(app_label, model_name)
|
||||||
related_models = set()
|
except LookupError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
# Get all relations to and from the old model before reloading,
|
||||||
|
# as _meta.apps may change
|
||||||
|
if delay:
|
||||||
|
related_models = get_related_models_tuples(old_model)
|
||||||
|
else:
|
||||||
|
related_models = get_related_models_recursive(old_model)
|
||||||
|
|
||||||
|
# Get all outgoing references from the model to be rendered
|
||||||
|
model_state = self.models[(app_label, model_name)]
|
||||||
|
# Directly related models are the models pointed to by ForeignKeys,
|
||||||
|
# OneToOneFields, and ManyToManyFields.
|
||||||
|
direct_related_models = set()
|
||||||
|
for name, field in model_state.fields:
|
||||||
|
if field.is_relation:
|
||||||
|
if field.remote_field.model == RECURSIVE_RELATIONSHIP_CONSTANT:
|
||||||
|
continue
|
||||||
|
rel_app_label, rel_model_name = _get_app_label_and_model_name(field.related_model, app_label)
|
||||||
|
direct_related_models.add((rel_app_label, rel_model_name.lower()))
|
||||||
|
|
||||||
|
# For all direct related models recursively get all related models.
|
||||||
|
related_models.update(direct_related_models)
|
||||||
|
for rel_app_label, rel_model_name in direct_related_models:
|
||||||
|
try:
|
||||||
|
rel_model = self.apps.get_model(rel_app_label, rel_model_name)
|
||||||
|
except LookupError:
|
||||||
|
pass
|
||||||
else:
|
else:
|
||||||
# Get all relations to and from the old model before reloading,
|
|
||||||
# as _meta.apps may change
|
|
||||||
if delay:
|
if delay:
|
||||||
related_models = get_related_models_tuples(old_model)
|
related_models.update(get_related_models_tuples(rel_model))
|
||||||
else:
|
else:
|
||||||
related_models = get_related_models_recursive(old_model)
|
related_models.update(get_related_models_recursive(rel_model))
|
||||||
|
|
||||||
# Get all outgoing references from the model to be rendered
|
# Include the model itself
|
||||||
model_state = self.models[(app_label, model_name)]
|
related_models.add((app_label, model_name))
|
||||||
# Directly related models are the models pointed to by ForeignKeys,
|
|
||||||
# OneToOneFields, and ManyToManyFields.
|
|
||||||
direct_related_models = set()
|
|
||||||
for name, field in model_state.fields:
|
|
||||||
if field.is_relation:
|
|
||||||
if field.remote_field.model == RECURSIVE_RELATIONSHIP_CONSTANT:
|
|
||||||
continue
|
|
||||||
rel_app_label, rel_model_name = _get_app_label_and_model_name(field.related_model, app_label)
|
|
||||||
direct_related_models.add((rel_app_label, rel_model_name.lower()))
|
|
||||||
|
|
||||||
# For all direct related models recursively get all related models.
|
return related_models
|
||||||
related_models.update(direct_related_models)
|
|
||||||
for rel_app_label, rel_model_name in direct_related_models:
|
|
||||||
try:
|
|
||||||
rel_model = self.apps.get_model(rel_app_label, rel_model_name)
|
|
||||||
except LookupError:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
if delay:
|
|
||||||
related_models.update(get_related_models_tuples(rel_model))
|
|
||||||
else:
|
|
||||||
related_models.update(get_related_models_recursive(rel_model))
|
|
||||||
|
|
||||||
# Include the model itself
|
def reload_model(self, app_label, model_name, delay=False):
|
||||||
related_models.add((app_label, model_name))
|
if 'apps' in self.__dict__: # hasattr would cache the property
|
||||||
|
related_models = self._find_reload_model(app_label, model_name, delay)
|
||||||
|
self._reload(related_models)
|
||||||
|
|
||||||
# Unregister all related models
|
def reload_models(self, models, delay=True):
|
||||||
with self.apps.bulk_update():
|
if 'apps' in self.__dict__: # hasattr would cache the property
|
||||||
for rel_app_label, rel_model_name in related_models:
|
related_models = set()
|
||||||
self.apps.unregister_model(rel_app_label, rel_model_name)
|
for app_label, model_name in models:
|
||||||
|
related_models.update(self._find_reload_model(app_label, model_name, delay))
|
||||||
|
self._reload(related_models)
|
||||||
|
|
||||||
states_to_be_rendered = []
|
def _reload(self, related_models):
|
||||||
# Gather all models states of those models that will be rerendered.
|
# Unregister all related models
|
||||||
# This includes:
|
with self.apps.bulk_update():
|
||||||
# 1. All related models of unmigrated apps
|
|
||||||
for model_state in self.apps.real_models:
|
|
||||||
if (model_state.app_label, model_state.name_lower) in related_models:
|
|
||||||
states_to_be_rendered.append(model_state)
|
|
||||||
|
|
||||||
# 2. All related models of migrated apps
|
|
||||||
for rel_app_label, rel_model_name in related_models:
|
for rel_app_label, rel_model_name in related_models:
|
||||||
try:
|
self.apps.unregister_model(rel_app_label, rel_model_name)
|
||||||
model_state = self.models[rel_app_label, rel_model_name]
|
|
||||||
except KeyError:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
states_to_be_rendered.append(model_state)
|
|
||||||
|
|
||||||
# Render all models
|
states_to_be_rendered = []
|
||||||
self.apps.render_multiple(states_to_be_rendered)
|
# Gather all models states of those models that will be rerendered.
|
||||||
|
# This includes:
|
||||||
|
# 1. All related models of unmigrated apps
|
||||||
|
for model_state in self.apps.real_models:
|
||||||
|
if (model_state.app_label, model_state.name_lower) in related_models:
|
||||||
|
states_to_be_rendered.append(model_state)
|
||||||
|
|
||||||
|
# 2. All related models of migrated apps
|
||||||
|
for rel_app_label, rel_model_name in related_models:
|
||||||
|
try:
|
||||||
|
model_state = self.models[rel_app_label, rel_model_name]
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
states_to_be_rendered.append(model_state)
|
||||||
|
|
||||||
|
# Render all models
|
||||||
|
self.apps.render_multiple(states_to_be_rendered)
|
||||||
|
|
||||||
def clone(self):
|
def clone(self):
|
||||||
"Returns an exact copy of this ProjectState"
|
"Returns an exact copy of this ProjectState"
|
||||||
|
|
Loading…
Reference in New Issue