Просмотр исходного кода

Introduce ObjectAttribute for displaying read-only instance attributes on forms

Jeremy Stretch 1 год назад
Родитель
Сommit
8f03a19b5f

+ 4 - 0
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

+ 0 - 1
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:

+ 5 - 0
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')

+ 0 - 1
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:

+ 0 - 19
netbox/templates/extras/imageattachment_edit.html

@@ -1,19 +0,0 @@
-{% extends 'generic/object_edit.html' %}
-{% load helpers %}
-{% load form_helpers %}
-
-{% block form %}
-  <div class="field-group mb-5">
-    <div class="row mb-3">
-      <label class="col-sm-3 col-form-label text-lg-end required">
-        {{ object.parent|meta:"verbose_name"|bettertitle }}
-      </label>
-      <div class="col-sm-9">
-        <div class="form-control-plaintext">
-          {{ object.parent|linkify }}
-        </div>
-      </div>
-    </div>
-    {% render_form form %}
-  </div>
-{% endblock form %}

+ 0 - 19
netbox/templates/ipam/fhrpgroupassignment_edit.html

@@ -1,19 +0,0 @@
-{% extends 'generic/object_edit.html' %}
-{% load form_helpers %}
-{% load i18n %}
-
-{% block form %}
-  <div class="field-group my-5">
-    <div class="row">
-      <h5 class="col-9 offset-3">{% trans "FHRP Group Assignment" %}</h5>
-    </div>
-    <div class="row mb-3">
-        <label class="col-sm-3 col-form-label text-lg-end">{% trans "Interface" %}</label>
-        <div class="col">
-            <input class="form-control" value="{{ form.instance.interface }}" disabled />
-        </div>
-    </div>
-    {% render_field form.group %}
-    {% render_field form.priority %}
-  </div>
-{% endblock %}

+ 0 - 35
netbox/templates/tenancy/contactassignment_edit.html

@@ -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 %}
-  <div class="field-group my-5">
-    <div class="row">
-      <h5 class="col-9 offset-3">{% trans "Contact Assignment" %}</h5>
-    </div>
-    <div class="row mb-3">
-      <label class="col-sm-3 col-form-label text-lg-end">
-        {{ form.instance.object|meta:'verbose_name'|bettertitle }}
-      </label>
-      <div class="col">
-        <input class="form-control" value="{{ form.instance.object }}" disabled />
-      </div>
-    </div>
-    {% render_field form.group %}
-    {% render_field form.contact %}
-    {% render_field form.role %}
-    {% render_field form.priority %}
-    {% render_field form.tags %}
-  </div>
-
-  <div class="field-group mb-5">
-    <div class="row">
-      <h5 class="col-9 offset-3">{% trans "Custom Fields" %}</h5>
-    </div>
-    {% render_custom_fields form %}
-  </div>
-{% endblock %}

+ 5 - 0
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 = (

+ 0 - 1
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:

+ 7 - 1
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

+ 11 - 0
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 #}
+      <div class="row mb-3">
+        <label class="col-sm-3 col-form-label text-lg-end required">{{ title }}</label>
+        <div class="col">
+          <div class="form-control-plaintext">
+            {{ items.0|linkify }}
+          </div>
+        </div>
+      </div>
+
     {% elif layout == 'inline' %}
       {# Multiple form fields on the same line #}
       <div class="row mb-3">

+ 8 - 1
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(