Skip to content

Commit 1d4ef5a

Browse files
authored
Fixes: #42 - Ensure default values are populated in create form for multiobject fields (#218)
1 parent 782bdcc commit 1d4ef5a

File tree

2 files changed

+40
-4
lines changed

2 files changed

+40
-4
lines changed

netbox_custom_objects/field_types.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -754,7 +754,8 @@ def get_model_field(self, field, **kwargs):
754754

755755
# Extract our custom parameters and keep only Django field parameters
756756
field_kwargs = {k: v for k, v in kwargs.items() if not k.startswith('_')}
757-
field_kwargs.update({"default": field.default, "unique": field.unique})
757+
# Remove default from field_kwargs since ManyToManyField doesn't handle defaults the same way
758+
field_kwargs.update({"unique": field.unique})
758759

759760
is_self_referential = (
760761
content_type.app_label == APP_LABEL
@@ -825,15 +826,13 @@ def get_form_field(self, field, for_csv_import=False, **kwargs):
825826
return field_class(
826827
queryset=model.objects.all(),
827828
required=field.required,
828-
# Remove initial=field.default to allow Django to handle instance data properly
829829
to_field_name=to_field_name,
830830
)
831831
else:
832832
field_class = DynamicModelMultipleChoiceField
833833
return field_class(
834834
queryset=model.objects.all(),
835835
required=field.required,
836-
# Remove initial=field.default to allow Django to handle instance data properly
837836
query_params=(
838837
field.related_object_filter
839838
if hasattr(field, "related_object_filter")

netbox_custom_objects/views.py

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
from . import field_types, filtersets, forms, tables
2929
from .models import CustomObject, CustomObjectType, CustomObjectTypeField
3030
from extras.choices import CustomFieldTypeChoices
31+
from netbox_custom_objects.constants import APP_LABEL
3132

3233
logger = logging.getLogger("netbox_custom_objects.views")
3334

@@ -493,13 +494,49 @@ def get_form(self, model):
493494

494495
# Create a custom __init__ method to set instance attributes
495496
def custom_init(self, *args, **kwargs):
496-
forms.NetBoxModelForm.__init__(self, *args, **kwargs)
497497
# Set the grouping info as instance attributes from the outer scope
498498
self.custom_object_type_fields = attrs["custom_object_type_fields"]
499499
self.custom_object_type_field_groups = attrs[
500500
"custom_object_type_field_groups"
501501
]
502502

503+
# Handle default values for MultiObject fields BEFORE calling parent __init__
504+
# This ensures the initial values are set before Django processes the form
505+
instance = kwargs.get('instance', None)
506+
if not instance or not instance.pk:
507+
# Only set defaults for new instances (not when editing existing ones)
508+
for field_name, field_obj in self.custom_object_type_fields.items():
509+
if field_obj.type == CustomFieldTypeChoices.TYPE_MULTIOBJECT:
510+
if field_obj.default and isinstance(field_obj.default, list):
511+
# Get the related model
512+
content_type = field_obj.related_object_type
513+
if content_type.app_label == APP_LABEL:
514+
# Custom object type
515+
from netbox_custom_objects.models import CustomObjectType
516+
custom_object_type_id = content_type.model.replace("table", "").replace("model", "")
517+
custom_object_type = CustomObjectType.objects.get(pk=custom_object_type_id)
518+
model = custom_object_type.get_model(skip_object_fields=True)
519+
else:
520+
# Regular NetBox model
521+
model = content_type.model_class()
522+
523+
try:
524+
# Query the database to get the actual objects
525+
initial_objects = model.objects.filter(pk__in=field_obj.default)
526+
# Convert to list of IDs for ModelMultipleChoiceField
527+
initial_ids = list(initial_objects.values_list('pk', flat=True))
528+
529+
# Set the initial value in the form's initial data
530+
if 'initial' not in kwargs:
531+
kwargs['initial'] = {}
532+
kwargs['initial'][field_name] = initial_ids
533+
except Exception:
534+
# If there's an error, don't set initial values
535+
pass
536+
537+
# Now call the parent __init__ with the modified kwargs
538+
forms.NetBoxModelForm.__init__(self, *args, **kwargs)
539+
503540
# Create a custom save method to properly handle M2M fields
504541
def custom_save(self, commit=True):
505542
# First save the instance to get the primary key

0 commit comments

Comments
 (0)