Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 17 additions & 15 deletions tortoise/migrations/schema_generator/operation_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,21 @@ def _create_model_operation(self, model_state: ModelState) -> CreateModel:
bases=[base.__name__ for base in model_state.bases],
)

@staticmethod
def _dependency_key_for_field(field: object) -> ModelKey | None:
if not isinstance(field, (ForeignKeyFieldInstance, ManyToManyFieldInstance)):
return None
ref = getattr(field, "model_name", None)
if not ref:
return None
if isinstance(ref, str):
parts = ref.split(".")
if len(parts) != 2:
return None
return parts[0], parts[1]
# model_name is a model class
return getattr(ref._meta, "app", ""), ref.__name__

@staticmethod
def _sort_by_dependencies(keys: list[ModelKey], state: State) -> list[ModelKey]:
"""Sort model keys so that FK/M2M dependencies come before dependents."""
Expand All @@ -70,21 +85,8 @@ def _sort_by_dependencies(keys: list[ModelKey], state: State) -> list[ModelKey]:
for key in keys:
model_state = state.models[key]
for field in model_state.fields.values():
if not isinstance(field, (ForeignKeyFieldInstance, ManyToManyFieldInstance)):
continue
ref = getattr(field, "model_name", None)
if not ref:
continue
if isinstance(ref, str):
parts = ref.split(".")
if len(parts) == 2:
dep_key: ModelKey = (parts[0], parts[1])
else:
continue
else:
# model_name is a model class
dep_key = (getattr(ref._meta, "app", ""), ref.__name__)
if dep_key in key_set and dep_key != key:
dep_key = OperationGenerator._dependency_key_for_field(field)
if dep_key and dep_key in key_set and dep_key != key:
deps[key].add(dep_key)

# Kahn's algorithm
Expand Down