[PR #19115] [MERGED] Fixes #18669 - Populate custom field default values #15532

Closed
opened 2025-12-30 00:22:31 +01:00 by adam · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/netbox-community/netbox/pull/19115
Author: @atownson
Created: 4/8/2025
Status: Merged
Merged: 4/15/2025
Merged by: @arthanson

Base: mainHead: issue_18669


📝 Commits (2)

  • 8cc35ec Populate omitted custom field default values on save
  • f70dc5f Remove unnecessary method to populate default custom fields

📊 Changes

2 files changed (+8 additions, -1 deletions)

View changed files

📝 netbox/ipam/forms/model_forms.py (+0 -1)
📝 netbox/netbox/models/features.py (+8 -0)

📄 Description

Fixes: #18669

While it is possible to fix this issue by modifying CustomFieldsDataField.to_internal_value() as such:

    def to_internal_value(self, data):
        if type(data) is not dict:
            raise ValidationError(
                "Invalid data format. Custom field data must be passed as a dictionary mapping field names to their "
                "values."
            )

        for cf in self._get_custom_fields():
            # Apply default values if omitted in the request
            if cf.name not in data and cf.default is not None:
                data[cf.name] = cf.default
            # Serialize object and multi-object values
            elif cf.name in data and data[cf.name] not in CUSTOMFIELD_EMPTY_VALUES and cf.type in (
                    CustomFieldTypeChoices.TYPE_OBJECT,
                    CustomFieldTypeChoices.TYPE_MULTIOBJECT
            ):
                serializer_class = get_serializer_for_model(cf.related_object_type.model_class())
                many = cf.type == CustomFieldTypeChoices.TYPE_MULTIOBJECT
                serializer = serializer_class(data=data[cf.name], nested=True, many=many, context=self.parent.context)
                if serializer.is_valid():
                    data[cf.name] = [obj['id'] for obj in serializer.data] if many else serializer.data['id']
                else:
                    raise ValidationError(_("Unknown related object(s): {name}").format(name=data[cf.name]))

        # If updating an existing instance, start with existing custom_field_data
        if self.parent.instance:
            data = {**self.parent.instance.custom_field_data, **data}

        return data

overriding the save() method on the mixin ensures the fix is applied to more than just the API endpoint (i.e. scripts). The populate_custom_field_defaults() method on the mixin is no longer needed but retained. It's function is to force the values of custom fields to the default rather than simply setting the default values if the fields are omitted. It was only used to populate newly created IP Addresses for FHRP groups. The save() method results are the same.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/netbox-community/netbox/pull/19115 **Author:** [@atownson](https://github.com/atownson) **Created:** 4/8/2025 **Status:** ✅ Merged **Merged:** 4/15/2025 **Merged by:** [@arthanson](https://github.com/arthanson) **Base:** `main` ← **Head:** `issue_18669` --- ### 📝 Commits (2) - [`8cc35ec`](https://github.com/netbox-community/netbox/commit/8cc35eca2725965c58b6caa7b382560c08e5adb3) Populate omitted custom field default values on save - [`f70dc5f`](https://github.com/netbox-community/netbox/commit/f70dc5f841c2c54cee631f7296001a332b053d98) Remove unnecessary method to populate default custom fields ### 📊 Changes **2 files changed** (+8 additions, -1 deletions) <details> <summary>View changed files</summary> 📝 `netbox/ipam/forms/model_forms.py` (+0 -1) 📝 `netbox/netbox/models/features.py` (+8 -0) </details> ### 📄 Description ### Fixes: #18669 While it is possible to fix this issue by modifying [CustomFieldsDataField.to_internal_value()](https://github.com/netbox-community/netbox/blob/92317248a36c0c57ecfde97d9690cad35fe47d81/netbox/extras/api/customfields.py#L70) as such: ``` def to_internal_value(self, data): if type(data) is not dict: raise ValidationError( "Invalid data format. Custom field data must be passed as a dictionary mapping field names to their " "values." ) for cf in self._get_custom_fields(): # Apply default values if omitted in the request if cf.name not in data and cf.default is not None: data[cf.name] = cf.default # Serialize object and multi-object values elif cf.name in data and data[cf.name] not in CUSTOMFIELD_EMPTY_VALUES and cf.type in ( CustomFieldTypeChoices.TYPE_OBJECT, CustomFieldTypeChoices.TYPE_MULTIOBJECT ): serializer_class = get_serializer_for_model(cf.related_object_type.model_class()) many = cf.type == CustomFieldTypeChoices.TYPE_MULTIOBJECT serializer = serializer_class(data=data[cf.name], nested=True, many=many, context=self.parent.context) if serializer.is_valid(): data[cf.name] = [obj['id'] for obj in serializer.data] if many else serializer.data['id'] else: raise ValidationError(_("Unknown related object(s): {name}").format(name=data[cf.name])) # If updating an existing instance, start with existing custom_field_data if self.parent.instance: data = {**self.parent.instance.custom_field_data, **data} return data ``` overriding the `save()` method on the mixin ensures the fix is applied to more than just the API endpoint (i.e. scripts). The `populate_custom_field_defaults()` method on the mixin is no longer needed but retained. It's function is to force the values of custom fields to the default rather than simply setting the default values if the fields are omitted. It was only used to populate newly created IP Addresses for FHRP groups. The `save()` method results are the same. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
adam added the pull-request label 2025-12-30 00:22:31 +01:00
adam closed this issue 2025-12-30 00:22:31 +01:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/netbox#15532