Skip to content

Commit 33e8aea

Browse files
committed
Revert using LazyForeignKey for cross-referential object fields
1 parent 4068a18 commit 33e8aea

File tree

1 file changed

+31
-10
lines changed

1 file changed

+31
-10
lines changed

netbox_custom_objects/field_types.py

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -388,7 +388,8 @@ def get_model_field(self, field, **kwargs):
388388
to_model = content_type.model
389389

390390
# Extract our custom parameters and keep only Django field parameters
391-
field_kwargs = self._safe_kwargs(**kwargs)
391+
generating_models = kwargs.pop('_generating_models', getattr(self, '_generating_models', set()))
392+
field_kwargs = {k: v for k, v in kwargs.items() if not k.startswith('_')}
392393
field_kwargs.update({"default": field.default, "unique": field.unique})
393394

394395
# Handle self-referential fields by using string references
@@ -400,15 +401,35 @@ def get_model_field(self, field, **kwargs):
400401
)
401402
custom_object_type = CustomObjectType.objects.get(pk=custom_object_type_id)
402403

403-
model_name = f"{APP_LABEL}.{custom_object_type.get_table_model_name(custom_object_type.id)}"
404-
f = LazyForeignKey(
405-
model_name,
406-
null=True,
407-
blank=True,
408-
on_delete=models.CASCADE,
409-
**field_kwargs
410-
)
411-
return f
404+
# Check if this is a self-referential field
405+
if custom_object_type.id == field.custom_object_type.id:
406+
# For self-referential fields, use LazyForeignKey to defer resolution
407+
model_name = f"{APP_LABEL}.{custom_object_type.get_table_model_name(custom_object_type.id)}"
408+
f = LazyForeignKey(
409+
model_name,
410+
null=True,
411+
blank=True,
412+
on_delete=models.CASCADE,
413+
**field_kwargs
414+
)
415+
return f
416+
else:
417+
# For cross-referential fields, use skip_object_fields to avoid infinite loops
418+
# Check if we're in a recursion situation using the parameter or stored attribute
419+
if generating_models and custom_object_type.id in generating_models:
420+
# We're in a circular reference, don't call get_model() to prevent recursion
421+
# Use a string reference instead
422+
model_name = f"{APP_LABEL}.{custom_object_type.get_table_model_name(custom_object_type.id)}"
423+
f = models.ForeignKey(
424+
model_name,
425+
null=True,
426+
blank=True,
427+
on_delete=models.CASCADE,
428+
**field_kwargs
429+
)
430+
return f
431+
else:
432+
model = custom_object_type.get_model(skip_object_fields=True)
412433
else:
413434
# to_model = content_type.model_class()._meta.object_name
414435
to_ct = f"{content_type.app_label}.{to_model}"

0 commit comments

Comments
 (0)