def get_deferred_foreign_key_columns(
models: list[type[SyncableMixin]],
graph: DependencyGraph,
) -> list[DeferredForeignKey]:
label_to_model = {m._meta.label: m for m in models}
syncable_labels = set(label_to_model.keys())
result: list[DeferredForeignKey] = []
for source_label, targets in graph.deferred_edges.items():
model = label_to_model[source_label]
for field in chain(
model._meta.concrete_fields,
model._meta.many_to_many,
):
if not field.is_relation:
continue
target_label = field.related_model._meta.label
if target_label in targets:
result.append(DeferredForeignKey(
source_label=source_label,
target_label=target_label,
field_name=field.name,
attribute_name=field.attname,
))
for model in models:
for field in model._meta.concrete_fields:
if not field.is_relation:
continue
if not getattr(field, 'null', False):
continue
target_label = field.related_model._meta.label
is_self_ref = (
target_label == model._meta.label
)
is_external = (
target_label not in syncable_labels
)
if not is_self_ref and not is_external:
continue
result.append(DeferredForeignKey(
source_label=model._meta.label,
target_label=target_label,
field_name=field.name,
attribute_name=field.attname,
))
return result