14
14
from django .utils .translation import gettext_lazy as _
15
15
from extras .choices import CustomFieldTypeChoices , CustomFieldUIEditableChoices
16
16
from utilities .api import get_serializer_for_model
17
- from utilities .forms .fields import (CSVChoiceField , CSVModelChoiceField ,
18
- CSVModelMultipleChoiceField , CSVMultipleChoiceField ,
19
- DynamicChoiceField ,
20
- DynamicMultipleChoiceField , JSONField ,
21
- LaxURLField )
17
+ from utilities .forms .fields import (
18
+ CSVChoiceField , CSVModelChoiceField ,
19
+ CSVModelMultipleChoiceField , CSVMultipleChoiceField ,
20
+ DynamicChoiceField , DynamicModelChoiceField ,
21
+ DynamicModelMultipleChoiceField ,
22
+ DynamicMultipleChoiceField , JSONField ,
23
+ LaxURLField ,
24
+ )
22
25
from utilities .forms .utils import add_blank_choice
23
- from utilities .forms .widgets import (APISelect , APISelectMultiple , DatePicker ,
24
- DateTimePicker )
26
+ from utilities .forms .widgets import (
27
+ APISelect , APISelectMultiple , DatePicker ,
28
+ DateTimePicker ,
29
+ )
25
30
from utilities .templatetags .builtins .filters import linkify , render_markdown
26
31
27
32
from netbox_custom_objects .constants import APP_LABEL
@@ -73,12 +78,6 @@ def get_filterform_field(self, field, **kwargs):
73
78
def get_form_field (self , field , ** kwargs ):
74
79
raise NotImplementedError
75
80
76
- def _filter_field_kwargs (self , kwargs ):
77
- """
78
- Filter out custom parameters that shouldn't be passed to Django field constructors.
79
- """
80
- return {k : v for k , v in kwargs .items () if not k .startswith ('_' ) and k != 'generating_models' }
81
-
82
81
def _safe_kwargs (self , ** kwargs ):
83
82
"""
84
83
Create a safe kwargs dict that can be passed to Django field constructors.
@@ -389,8 +388,7 @@ def get_model_field(self, field, **kwargs):
389
388
to_model = content_type .model
390
389
391
390
# Extract our custom parameters and keep only Django field parameters
392
- generating_models = kwargs .pop ('_generating_models' , getattr (self , '_generating_models' , set ()))
393
- field_kwargs = {k : v for k , v in kwargs .items () if not k .startswith ('_' )}
391
+ field_kwargs = self ._safe_kwargs (** kwargs )
394
392
field_kwargs .update ({"default" : field .default , "unique" : field .unique })
395
393
396
394
# Handle self-referential fields by using string references
@@ -402,35 +400,15 @@ def get_model_field(self, field, **kwargs):
402
400
)
403
401
custom_object_type = CustomObjectType .objects .get (pk = custom_object_type_id )
404
402
405
- # Check if this is a self-referential field
406
- if custom_object_type .id == field .custom_object_type .id :
407
- # For self-referential fields, use LazyForeignKey to defer resolution
408
- model_name = f"{ APP_LABEL } .{ custom_object_type .get_table_model_name (custom_object_type .id )} "
409
- f = LazyForeignKey (
410
- model_name ,
411
- null = True ,
412
- blank = True ,
413
- on_delete = models .CASCADE ,
414
- ** field_kwargs
415
- )
416
- return f
417
- else :
418
- # For cross-referential fields, use skip_object_fields to avoid infinite loops
419
- # Check if we're in a recursion situation using the parameter or stored attribute
420
- if generating_models and custom_object_type .id in generating_models :
421
- # We're in a circular reference, don't call get_model() to prevent recursion
422
- # Use a string reference instead
423
- model_name = f"{ APP_LABEL } .{ custom_object_type .get_table_model_name (custom_object_type .id )} "
424
- f = models .ForeignKey (
425
- model_name ,
426
- null = True ,
427
- blank = True ,
428
- on_delete = models .CASCADE ,
429
- ** field_kwargs
430
- )
431
- return f
432
- else :
433
- model = custom_object_type .get_model (skip_object_fields = True )
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
434
412
else :
435
413
# to_model = content_type.model_class()._meta.object_name
436
414
to_ct = f"{ content_type .app_label } .{ to_model } "
@@ -464,7 +442,6 @@ def get_form_field(self, field, for_csv_import=False, **kwargs):
464
442
if generating_models and custom_object_type .id in generating_models :
465
443
# We're in a circular reference, don't call get_model() to prevent recursion
466
444
# Use a minimal approach or return a basic field
467
- from utilities .forms .fields import DynamicModelChoiceField
468
445
return DynamicModelChoiceField (
469
446
queryset = custom_object_type .get_model (skip_object_fields = True ).objects .all (),
470
447
required = field .required ,
@@ -488,7 +465,6 @@ def get_form_field(self, field, for_csv_import=False, **kwargs):
488
465
to_field_name = to_field_name ,
489
466
)
490
467
else :
491
- from utilities .forms .fields import DynamicModelChoiceField
492
468
field_class = DynamicModelChoiceField
493
469
return field_class (
494
470
queryset = model .objects .all (),
@@ -523,8 +499,7 @@ def after_model_generation(self, instance, model, field_name):
523
499
This ensures that self-referential fields point to the correct model class.
524
500
"""
525
501
# Check if this field has a resolution method
526
- resolve_method = getattr (model , f'_resolve_{ field_name } _model' , None )
527
- if resolve_method :
502
+ if resolve_method := getattr (model , f'_resolve_{ field_name } _model' , None ):
528
503
resolve_method (model )
529
504
530
505
@@ -790,7 +765,6 @@ def get_form_field(self, field, for_csv_import=False, **kwargs):
790
765
if generating_models and custom_object_type .id in generating_models :
791
766
# We're in a circular reference, don't call get_model() to prevent recursion
792
767
# Use a minimal approach or return a basic field
793
- from utilities .forms .fields import DynamicModelMultipleChoiceField
794
768
return DynamicModelMultipleChoiceField (
795
769
queryset = custom_object_type .get_model (skip_object_fields = True ).objects .all (),
796
770
required = field .required ,
@@ -814,7 +788,6 @@ def get_form_field(self, field, for_csv_import=False, **kwargs):
814
788
to_field_name = to_field_name ,
815
789
)
816
790
else :
817
- from utilities .forms .fields import DynamicModelMultipleChoiceField
818
791
field_class = DynamicModelMultipleChoiceField
819
792
return field_class (
820
793
queryset = model .objects .all (),
@@ -839,8 +812,6 @@ def get_serializer_field(self, field, **kwargs):
839
812
if related_model_class ._meta .app_label == APP_LABEL :
840
813
from netbox_custom_objects .api .serializers import get_serializer_class
841
814
serializer = get_serializer_class (related_model_class , skip_object_fields = True )
842
- # if not related_model_class:
843
- # raise NotImplementedError("Custom object serializers not implemented")
844
815
else :
845
816
serializer = get_serializer_for_model (related_model_class )
846
817
return serializer (required = field .required , nested = True , many = True )
0 commit comments