Represent the entire project's overall state. This is the item that is passed around - do it here rather than at the app level so that cross-app FKs/etc. resolve properly.
| 93 | |
| 94 | |
| 95 | class ProjectState: |
| 96 | """ |
| 97 | Represent the entire project's overall state. This is the item that is |
| 98 | passed around - do it here rather than at the app level so that cross-app |
| 99 | FKs/etc. resolve properly. |
| 100 | """ |
| 101 | |
| 102 | def __init__(self, models=None, real_apps=None): |
| 103 | self.models = models or {} |
| 104 | # Apps to include from main registry, usually unmigrated ones |
| 105 | if real_apps is None: |
| 106 | real_apps = set() |
| 107 | else: |
| 108 | assert isinstance(real_apps, set) |
| 109 | self.real_apps = real_apps |
| 110 | self.is_delayed = False |
| 111 | # {remote_model_key: {model_key: {field_name: field}}} |
| 112 | self._relations = None |
| 113 | |
| 114 | @property |
| 115 | def relations(self): |
| 116 | if self._relations is None: |
| 117 | self.resolve_fields_and_relations() |
| 118 | return self._relations |
| 119 | |
| 120 | def add_model(self, model_state): |
| 121 | model_key = model_state.app_label, model_state.name_lower |
| 122 | self.models[model_key] = model_state |
| 123 | if self._relations is not None: |
| 124 | self.resolve_model_relations(model_key) |
| 125 | if "apps" in self.__dict__: # hasattr would cache the property |
| 126 | self.reload_model(*model_key) |
| 127 | |
| 128 | def remove_model(self, app_label, model_name): |
| 129 | model_key = app_label, model_name |
| 130 | del self.models[model_key] |
| 131 | if self._relations is not None: |
| 132 | self._relations.pop(model_key, None) |
| 133 | # Call list() since _relations can change size during iteration. |
| 134 | for related_model_key, model_relations in list(self._relations.items()): |
| 135 | model_relations.pop(model_key, None) |
| 136 | if not model_relations: |
| 137 | del self._relations[related_model_key] |
| 138 | if "apps" in self.__dict__: # hasattr would cache the property |
| 139 | self.apps.unregister_model(*model_key) |
| 140 | # Need to do this explicitly since unregister_model() doesn't clear |
| 141 | # the cache automatically (#24513) |
| 142 | self.apps.clear_cache() |
| 143 | |
| 144 | def rename_model(self, app_label, old_name, new_name): |
| 145 | # Add a new model. |
| 146 | old_name_lower = old_name.lower() |
| 147 | new_name_lower = new_name.lower() |
| 148 | renamed_model = self.models[app_label, old_name_lower].clone() |
| 149 | renamed_model.name = new_name |
| 150 | self.models[app_label, new_name_lower] = renamed_model |
| 151 | # Repoint all fields pointing to the old model to the new one. |
| 152 | old_model_tuple = (app_label, old_name_lower) |
no outgoing calls