diff --git a/netbox/extras/forms/model_forms.py b/netbox/extras/forms/model_forms.py
index 09d2d9535..4e62b3ab7 100644
--- a/netbox/extras/forms/model_forms.py
+++ b/netbox/extras/forms/model_forms.py
@@ -17,6 +17,7 @@ from utilities.forms.fields import (
CommentField, ContentTypeChoiceField, ContentTypeMultipleChoiceField, DynamicModelChoiceField,
DynamicModelMultipleChoiceField, JSONField, SlugField,
)
+from utilities.forms.rendering import ObjectAttribute
from utilities.forms.widgets import ChoicesWidget, HTMXSelect
from virtualization.models import Cluster, ClusterGroup, ClusterType
@@ -526,6 +527,9 @@ class ConfigTemplateForm(SyncedDataMixin, forms.ModelForm):
class ImageAttachmentForm(forms.ModelForm):
+ fieldsets = (
+ (None, (ObjectAttribute('parent'), 'name', 'image')),
+ )
class Meta:
model = ImageAttachment
diff --git a/netbox/extras/views.py b/netbox/extras/views.py
index 1fa2a30aa..cb3fdd39c 100644
--- a/netbox/extras/views.py
+++ b/netbox/extras/views.py
@@ -759,7 +759,6 @@ class ImageAttachmentListView(generic.ObjectListView):
class ImageAttachmentEditView(generic.ObjectEditView):
queryset = ImageAttachment.objects.all()
form = forms.ImageAttachmentForm
- template_name = 'extras/imageattachment_edit.html'
def alter_object(self, instance, request, args, kwargs):
if not instance.pk:
diff --git a/netbox/ipam/forms/model_forms.py b/netbox/ipam/forms/model_forms.py
index 47087139a..07f782f7f 100644
--- a/netbox/ipam/forms/model_forms.py
+++ b/netbox/ipam/forms/model_forms.py
@@ -16,6 +16,7 @@ from utilities.forms.fields import (
CommentField, ContentTypeChoiceField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, NumericArrayField,
SlugField,
)
+from utilities.forms.rendering import ObjectAttribute
from utilities.forms.widgets import DatePicker
from virtualization.models import Cluster, ClusterGroup, VirtualMachine, VMInterface
@@ -502,6 +503,10 @@ class FHRPGroupAssignmentForm(forms.ModelForm):
queryset=FHRPGroup.objects.all()
)
+ fieldsets = (
+ (None, (ObjectAttribute('interface'), 'group', 'priority')),
+ )
+
class Meta:
model = FHRPGroupAssignment
fields = ('group', 'priority')
diff --git a/netbox/ipam/views.py b/netbox/ipam/views.py
index 9c4a9a102..79716f082 100644
--- a/netbox/ipam/views.py
+++ b/netbox/ipam/views.py
@@ -1059,7 +1059,6 @@ class FHRPGroupBulkDeleteView(generic.BulkDeleteView):
class FHRPGroupAssignmentEditView(generic.ObjectEditView):
queryset = FHRPGroupAssignment.objects.all()
form = forms.FHRPGroupAssignmentForm
- template_name = 'ipam/fhrpgroupassignment_edit.html'
def alter_object(self, instance, request, args, kwargs):
if not instance.pk:
diff --git a/netbox/templates/extras/imageattachment_edit.html b/netbox/templates/extras/imageattachment_edit.html
deleted file mode 100644
index 75b2ce48b..000000000
--- a/netbox/templates/extras/imageattachment_edit.html
+++ /dev/null
@@ -1,19 +0,0 @@
-{% extends 'generic/object_edit.html' %}
-{% load helpers %}
-{% load form_helpers %}
-
-{% block form %}
-
-
-
-
-
- {{ object.parent|linkify }}
-
-
-
- {% render_form form %}
-
-{% endblock form %}
diff --git a/netbox/templates/ipam/fhrpgroupassignment_edit.html b/netbox/templates/ipam/fhrpgroupassignment_edit.html
deleted file mode 100644
index bbc1505f2..000000000
--- a/netbox/templates/ipam/fhrpgroupassignment_edit.html
+++ /dev/null
@@ -1,19 +0,0 @@
-{% extends 'generic/object_edit.html' %}
-{% load form_helpers %}
-{% load i18n %}
-
-{% block form %}
-
-
-
{% trans "FHRP Group Assignment" %}
-
-
-
-
-
-
-
- {% render_field form.group %}
- {% render_field form.priority %}
-
-{% endblock %}
diff --git a/netbox/templates/tenancy/contactassignment_edit.html b/netbox/templates/tenancy/contactassignment_edit.html
deleted file mode 100644
index 342debcbb..000000000
--- a/netbox/templates/tenancy/contactassignment_edit.html
+++ /dev/null
@@ -1,35 +0,0 @@
-{% extends 'generic/object_edit.html' %}
-{% load helpers %}
-{% load form_helpers %}
-{% load i18n %}
-
-{% block form %}
- {% for field in form.hidden_fields %}
- {{ field }}
- {% endfor %}
-
-
-
{% trans "Contact Assignment" %}
-
-
-
-
-
-
-
- {% render_field form.group %}
- {% render_field form.contact %}
- {% render_field form.role %}
- {% render_field form.priority %}
- {% render_field form.tags %}
-
-
-
-
-
{% trans "Custom Fields" %}
-
- {% render_custom_fields form %}
-
-{% endblock %}
diff --git a/netbox/tenancy/forms/model_forms.py b/netbox/tenancy/forms/model_forms.py
index 140d9cf9a..7dcb4e433 100644
--- a/netbox/tenancy/forms/model_forms.py
+++ b/netbox/tenancy/forms/model_forms.py
@@ -4,6 +4,7 @@ from django.utils.translation import gettext_lazy as _
from netbox.forms import NetBoxModelForm
from tenancy.models import *
from utilities.forms.fields import CommentField, DynamicModelChoiceField, SlugField
+from utilities.forms.rendering import ObjectAttribute
__all__ = (
'ContactAssignmentForm',
@@ -140,6 +141,10 @@ class ContactAssignmentForm(NetBoxModelForm):
queryset=ContactRole.objects.all()
)
+ fieldsets = (
+ (None, (ObjectAttribute('object'), 'group', 'contact', 'role', 'priority', 'tags')),
+ )
+
class Meta:
model = ContactAssignment
fields = (
diff --git a/netbox/tenancy/views.py b/netbox/tenancy/views.py
index 4c4d263df..d30793a16 100644
--- a/netbox/tenancy/views.py
+++ b/netbox/tenancy/views.py
@@ -369,7 +369,6 @@ class ContactAssignmentListView(generic.ObjectListView):
class ContactAssignmentEditView(generic.ObjectEditView):
queryset = ContactAssignment.objects.all()
form = forms.ContactAssignmentForm
- template_name = 'tenancy/contactassignment_edit.html'
def alter_object(self, instance, request, args, kwargs):
if not instance.pk:
diff --git a/netbox/utilities/forms/rendering.py b/netbox/utilities/forms/rendering.py
index ad87930a9..d60f3f061 100644
--- a/netbox/utilities/forms/rendering.py
+++ b/netbox/utilities/forms/rendering.py
@@ -3,8 +3,8 @@ import string
from functools import cached_property
__all__ = (
- 'FieldGroup',
'InlineFields',
+ 'ObjectAttribute',
'TabbedFieldGroups',
)
@@ -41,3 +41,9 @@ class TabbedFieldGroups:
'fields': group.field_names,
} for i, group in enumerate(self.groups, start=1)
]
+
+
+class ObjectAttribute:
+
+ def __init__(self, name):
+ self.name = name
diff --git a/netbox/utilities/templates/form_helpers/render_fieldset.html b/netbox/utilities/templates/form_helpers/render_fieldset.html
index ee1f50293..d4c7981f7 100644
--- a/netbox/utilities/templates/form_helpers/render_fieldset.html
+++ b/netbox/utilities/templates/form_helpers/render_fieldset.html
@@ -12,6 +12,17 @@
{# Single form field #}
{% render_field items.0 %}
+ {% elif layout == 'attribute' %}
+ {# A static attribute of the form's instance #}
+
+
+
+
+ {{ items.0|linkify }}
+
+
+
+
{% elif layout == 'inline' %}
{# Multiple form fields on the same line #}
diff --git a/netbox/utilities/templatetags/form_helpers.py b/netbox/utilities/templatetags/form_helpers.py
index c55a6b98b..e336ac21b 100644
--- a/netbox/utilities/templatetags/form_helpers.py
+++ b/netbox/utilities/templatetags/form_helpers.py
@@ -1,6 +1,6 @@
from django import template
-from utilities.forms.rendering import InlineFields, TabbedFieldGroups
+from utilities.forms.rendering import InlineFields, ObjectAttribute, TabbedFieldGroups
__all__ = (
'getfield',
@@ -81,6 +81,13 @@ def render_fieldset(form, fieldset, heading=None):
('tabs', None, tabs)
)
+ elif type(item) is ObjectAttribute:
+ value = getattr(form.instance, item.name)
+ label = value._meta.verbose_name if hasattr(value, '_meta') else item.name
+ rows.append(
+ ('attribute', label.title(), [value])
+ )
+
# A single form field
elif item in form.fields:
rows.append(