diff --git a/docs/release-notes/version-3.3.md b/docs/release-notes/version-3.3.md index 51d595123..7e8fd50e3 100644 --- a/docs/release-notes/version-3.3.md +++ b/docs/release-notes/version-3.3.md @@ -105,6 +105,7 @@ Custom field UI visibility has no impact on API operation. * [#9765](https://github.com/netbox-community/netbox/issues/9765) - Report correct segment count under cable trace UI view * [#9794](https://github.com/netbox-community/netbox/issues/9794) - Fix link to connect a rear port to a circuit termination * [#9818](https://github.com/netbox-community/netbox/issues/9818) - Fix circuit side selection when connecting a cable to a circuit termination +* [#9829](https://github.com/netbox-community/netbox/issues/9829) - Arrange custom fields by group when editing objects * [#9843](https://github.com/netbox-community/netbox/issues/9843) - Fix rendering of custom field values (regression from #9647) * [#9844](https://github.com/netbox-community/netbox/issues/9844) - Fix interface api request when creating/editing L2VPN termination diff --git a/netbox/extras/forms/customfields.py b/netbox/extras/forms/customfields.py index 4cf8b5e0a..7574f4f2b 100644 --- a/netbox/extras/forms/customfields.py +++ b/netbox/extras/forms/customfields.py @@ -19,6 +19,7 @@ class CustomFieldsMixin: def __init__(self, *args, **kwargs): self.custom_fields = {} + self.custom_field_groups = {} super().__init__(*args, **kwargs) @@ -58,3 +59,6 @@ class CustomFieldsMixin: # Annotate the field in the list of CustomField form fields self.custom_fields[field_name] = customfield + if customfield.group_name not in self.custom_field_groups: + self.custom_field_groups[customfield.group_name] = [] + self.custom_field_groups[customfield.group_name].append(field_name) diff --git a/netbox/netbox/forms/base.py b/netbox/netbox/forms/base.py index 0e232af1d..2676e4cde 100644 --- a/netbox/netbox/forms/base.py +++ b/netbox/netbox/forms/base.py @@ -94,30 +94,19 @@ class NetBoxModelBulkEditForm(BootstrapMixin, CustomFieldsMixin, forms.Form): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) + self.fields['pk'].queryset = self.model.objects.all() + self._extend_nullable_fields() + def _get_form_field(self, customfield): return customfield.to_form_field(set_initial=False, enforce_required=False) - def _append_customfield_fields(self): - """ - Append form fields for all CustomFields assigned to this object type. - """ - nullable_custom_fields = [] - for customfield in self._get_custom_fields(self._get_content_type()): - field_name = f'cf_{customfield.name}' - self.fields[field_name] = self._get_form_field(customfield) - - # Record non-required custom fields as nullable - if not customfield.required: - nullable_custom_fields.append(field_name) - - # Annotate the field in the list of CustomField form fields - self.custom_fields[field_name] = customfield - - # Annotate nullable custom fields (if any) on the form instance - if nullable_custom_fields: - self.nullable_fields = (*self.nullable_fields, *nullable_custom_fields) + def _extend_nullable_fields(self): + nullable_custom_fields = [ + name for name, customfield in self.custom_fields.items() if not customfield.required + ] + self.nullable_fields = (*self.nullable_fields, *nullable_custom_fields) class NetBoxModelFilterSetForm(BootstrapMixin, CustomFieldsMixin, forms.Form): diff --git a/netbox/templates/inc/panels/custom_fields.html b/netbox/templates/inc/panels/custom_fields.html index 90059447f..616b1c712 100644 --- a/netbox/templates/inc/panels/custom_fields.html +++ b/netbox/templates/inc/panels/custom_fields.html @@ -7,7 +7,7 @@
{% for group_name, fields in custom_fields.items %} {% if group_name %} -
{{ group_name }}
+
{{ group_name }}
{% endif %} {% for field, value in fields.items %} diff --git a/netbox/utilities/templates/form_helpers/render_custom_fields.html b/netbox/utilities/templates/form_helpers/render_custom_fields.html index f3e5bffa9..6b0b2840b 100644 --- a/netbox/utilities/templates/form_helpers/render_custom_fields.html +++ b/netbox/utilities/templates/form_helpers/render_custom_fields.html @@ -1,7 +1,12 @@ {% load form_helpers %} -{% for field in form %} - {% if field.name in form.custom_fields %} - {% render_field field %} - {% endif %} +{% for group, fields in form.custom_field_groups.items %} + {% if group %} +
+
{{ group }}
+
+ {% endif %} + {% for name in fields %} + {% render_field form|getfield:name %} + {% endfor %} {% endfor %}