158 | | # Prepare field lists, and prepare a list of the fields that used |
159 | | # through models in the old state so we can make dependencies |
160 | | # from the through model deletion to the field that uses it. |
161 | | self.kept_model_keys = set(self.old_model_keys).intersection(self.new_model_keys) |
162 | | self.kept_proxy_keys = set(self.old_proxy_keys).intersection(self.new_proxy_keys) |
163 | | self.kept_unmanaged_keys = set(self.old_unmanaged_keys).intersection(self.new_unmanaged_keys) |
164 | | self.through_users = {} |
165 | | self.old_field_keys = set() |
166 | | self.new_field_keys = set() |
167 | | for app_label, model_name in sorted(self.kept_model_keys): |
168 | | old_model_name = self.renamed_models.get((app_label, model_name), model_name) |
169 | | old_model_state = self.from_state.models[app_label, old_model_name] |
170 | | new_model_state = self.to_state.models[app_label, model_name] |
171 | | self.old_field_keys.update((app_label, model_name, x) for x, y in old_model_state.fields) |
172 | | self.new_field_keys.update((app_label, model_name, x) for x, y in new_model_state.fields) |
173 | | |
174 | | # Through model map generation |
175 | | for app_label, model_name in sorted(self.old_model_keys): |
176 | | old_model_name = self.renamed_models.get((app_label, model_name), model_name) |
177 | | old_model_state = self.from_state.models[app_label, old_model_name] |
178 | | for field_name, field in old_model_state.fields: |
179 | | old_field = self.old_apps.get_model(app_label, old_model_name)._meta.get_field(field_name) |
180 | | if (hasattr(old_field, "remote_field") and getattr(old_field.remote_field, "through", None) |
181 | | and not old_field.remote_field.through._meta.auto_created): |
182 | | through_key = ( |
183 | | old_field.remote_field.through._meta.app_label, |
184 | | old_field.remote_field.through._meta.model_name, |
185 | | ) |
186 | | self.through_users[through_key] = (app_label, old_model_name, field_name) |
| 158 | # Prepare lists of fields and generate through model map |
| 159 | self._prepare_field_lists() |
| 160 | self._generate_through_model_map() |
223 | | # Now, we need to chop the lists of operations up into migrations with |
224 | | # dependencies on each other. |
225 | | # We do this by stepping up an app's list of operations until we |
226 | | # find one that has an outgoing dependency that isn't in another app's |
227 | | # migration yet (hasn't been chopped off its list). We then chop off the |
228 | | # operations before it into a migration and move onto the next app. |
229 | | # If we loop back around without doing anything, there's a circular |
230 | | # dependency (which _should_ be impossible as the operations are all |
231 | | # split at this point so they can't depend and be depended on) |
| 196 | self._build_migration_list(graph) |
| 197 | |
| 198 | # OK, add in internal dependencies among the migrations |
| 199 | for app_label, migrations in self.migrations.items(): |
| 200 | for m1, m2 in zip(migrations, migrations[1:]): |
| 201 | m2.dependencies.append((app_label, m1.name)) |
| 202 | |
| 203 | # De-dupe dependencies |
| 204 | for app_label, migrations in self.migrations.items(): |
| 205 | for migration in migrations: |
| 206 | migration.dependencies = list(set(migration.dependencies)) |
| 207 | |
| 208 | # Optimize migrations |
| 209 | for app_label, migrations in self.migrations.items(): |
| 210 | for migration in migrations: |
| 211 | migration.operations = MigrationOptimizer().optimize(migration.operations, app_label=app_label) |
| 212 | |
| 213 | return self.migrations |
| 214 | |
| 215 | def _prepare_field_lists(self): |
| 216 | """ |
| 217 | Prepare field lists, and prepare a list of the fields that used |
| 218 | through models in the old state so we can make dependencies |
| 219 | from the through model deletion to the field that uses it. |
| 220 | """ |
| 221 | |
| 222 | self.kept_model_keys = set(self.old_model_keys).intersection(self.new_model_keys) |
| 223 | self.kept_proxy_keys = set(self.old_proxy_keys).intersection(self.new_proxy_keys) |
| 224 | self.kept_unmanaged_keys = set(self.old_unmanaged_keys).intersection(self.new_unmanaged_keys) |
| 225 | self.through_users = {} |
| 226 | self.old_field_keys = set() |
| 227 | self.new_field_keys = set() |
| 228 | for app_label, model_name in sorted(self.kept_model_keys): |
| 229 | old_model_name = self.renamed_models.get((app_label, model_name), model_name) |
| 230 | old_model_state = self.from_state.models[app_label, old_model_name] |
| 231 | new_model_state = self.to_state.models[app_label, model_name] |
| 232 | self.old_field_keys.update((app_label, model_name, x) for x, y in old_model_state.fields) |
| 233 | self.new_field_keys.update((app_label, model_name, x) for x, y in new_model_state.fields) |
| 234 | |
| 235 | def _generate_through_model_map(self): |
| 236 | """ |
| 237 | Through model map generation |
| 238 | """ |
| 239 | |
| 240 | for app_label, model_name in sorted(self.old_model_keys): |
| 241 | old_model_name = self.renamed_models.get((app_label, model_name), model_name) |
| 242 | old_model_state = self.from_state.models[app_label, old_model_name] |
| 243 | for field_name, field in old_model_state.fields: |
| 244 | old_field = self.old_apps.get_model(app_label, old_model_name)._meta.get_field(field_name) |
| 245 | if (hasattr(old_field, "remote_field") and getattr(old_field.remote_field, "through", None) |
| 246 | and not old_field.remote_field.through._meta.auto_created): |
| 247 | through_key = ( |
| 248 | old_field.remote_field.through._meta.app_label, |
| 249 | old_field.remote_field.through._meta.model_name, |
| 250 | ) |
| 251 | self.through_users[through_key] = (app_label, old_model_name, field_name) |
| 252 | |
| 253 | def _build_migration_list(self, graph=None): |
| 254 | """ |
| 255 | We need to chop the lists of operations up into migrations with |
| 256 | dependencies on each other. We do this by stepping up an app's list of |
| 257 | operations until we find one that has an outgoing dependency that isn't |
| 258 | in another app's migration yet (hasn't been chopped off its list). We |
| 259 | then chop off the operations before it into a migration and move onto |
| 260 | the next app. If we loop back around without doing anything, there's a |
| 261 | circular dependency (which _should_ be impossible as the operations are |
| 262 | all split at this point so they can't depend and be depended on). |
| 263 | """ |