Przeglądaj źródła

Introduce InlineFields for rendering fields side-by-side

Jeremy Stretch 1 rok temu
rodzic
commit
f585c36d86

+ 17 - 0
netbox/dcim/forms/model_forms.py

@@ -16,6 +16,7 @@ from utilities.forms.fields import (
     CommentField, ContentTypeChoiceField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, JSONField,
     NumericArrayField, SlugField,
 )
+from utilities.forms.rendering import InlineFields
 from utilities.forms.widgets import APISelect, ClearableFileInput, HTMXSelect, NumberWithOptions, SelectWithPK
 from virtualization.models import Cluster
 from wireless.models import WirelessLAN, WirelessLANGroup
@@ -227,6 +228,22 @@ class RackForm(TenancyForm, NetBoxModelForm):
     )
     comments = CommentField()
 
+    fieldsets = (
+        (_('Rack'), ('site', 'location', 'name', 'status', 'role', 'description', 'tags')),
+        (_('Inventory Control'), ('facility_id', 'serial', 'asset_tag')),
+        (_('Tenancy'), ('tenant_group', 'tenant')),
+        (_('Dimensions'), (
+            'type',
+            'width',
+            'starting_unit',
+            'u_height',
+            InlineFields('outer_width', 'outer_depth', 'outer_unit', label=_('Outer Dimensions')),
+            InlineFields('weight', 'max_weight', 'weight_unit', label=_('Weight')),
+            'mounting_depth',
+            'desc_units',
+        )),
+    )
+
     class Meta:
         model = Rack
         fields = [

+ 0 - 1
netbox/dcim/views.py

@@ -727,7 +727,6 @@ class RackNonRackedView(generic.ObjectChildrenView):
 class RackEditView(generic.ObjectEditView):
     queryset = Rack.objects.all()
     form = forms.RackForm
-    template_name = 'dcim/rack_edit.html'
 
 
 @register_model_view(Rack, 'delete')

+ 0 - 90
netbox/templates/dcim/rack_edit.html

@@ -1,90 +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 "Rack" %}</h5>
-        </div>
-        {% render_field form.site %}
-        {% render_field form.location %}
-        {% render_field form.name %}
-        {% render_field form.status %}
-        {% render_field form.role %}
-        {% render_field form.description %}
-        {% render_field form.tags %}
-    </div>
-
-    <div class="field-group my-5">
-        <div class="row">
-          <h5 class="col-9 offset-3">{% trans "Inventory Control" %}</h5>
-        </div>
-        {% render_field form.facility_id %}
-        {% render_field form.serial %}
-        {% render_field form.asset_tag %}
-    </div>
-
-    <div class="field-group my-5">
-        <div class="row">
-          <h5 class="col-9 offset-3">{% trans "Tenancy" %}</h5>
-        </div>
-        {% render_field form.tenant_group %}
-        {% render_field form.tenant %}
-    </div>
-
-    <div class="field-group my-5">
-        <div class="row">
-          <h5 class="col-9 offset-3">{% trans "Dimensions" %}</h5>
-        </div>
-        {% render_field form.type %}
-        {% render_field form.width %}
-        {% render_field form.starting_unit %}
-        {% render_field form.u_height %}
-        <div class="row mb-3">
-            <label class="col col-md-3 col-form-label text-lg-end">{% trans "Outer Dimensions" %}</label>
-            <div class="col col-md-3 mb-1">
-                {{ form.outer_width }}
-                <div class="form-text">{% trans "Width" %}</div>
-            </div>
-            <div class="col col-md-3 mb-1">
-                {{ form.outer_depth }}
-                <div class="form-text">{% trans "Depth" %}</div>
-            </div>
-            <div class="col col-md-3 mb-1">
-                {{ form.outer_unit }}
-                <div class="form-text">{% trans "Unit" %}</div>
-            </div>
-        </div>
-        <div class="row mb-3">
-            <label class="col col-md-3 col-form-label text-lg-end">{% trans "Weight" %}</label>
-            <div class="col col-md-3 mb-1">
-                {{ form.weight }}
-                <div class="form-text">{% trans "Weight" %}</div>
-            </div>
-            <div class="col col-md-3 mb-1">
-                {{ form.max_weight }}
-                <div class="form-text">{% trans "Maximum Weight" %}</div>
-            </div>
-            <div class="col col-md-3 mb-1">
-                {{ form.weight_unit }}
-                <div class="form-text">{% trans "Unit" %}</div>
-            </div>
-        </div>
-        {% render_field form.mounting_depth %}
-        {% render_field form.desc_units %}
-    </div>
-
-    {% if form.custom_fields %}
-      <div class="field-group my-5">
-        <div class="row">
-          <h5 class="col-9 offset-3">{% trans "Custom Fields" %}</h5>
-        </div>
-          {% render_custom_fields form %}
-      </div>
-    {% endif %}
-
-    <div class="field-group my-5">
-      {% render_field form.comments %}
-    </div>
-{% endblock %}

+ 2 - 15
netbox/templates/htmx/form.html

@@ -9,21 +9,8 @@
   {% endfor %}
 
   {# Render grouped fields according to Form #}
-  {% for group, fields in form.fieldsets %}
-    <div class="field-group mb-5">
-      {% if group %}
-        <div class="row">
-          <h5 class="col-9 offset-3">{{ group }}</h5>
-        </div>
-      {% endif %}
-      {% for name in fields %}
-        {% with field=form|getfield:name %}
-          {% if field and not field.field.widget.is_hidden %}
-            {% render_field field %}
-          {% endif %}
-        {% endwith %}
-      {% endfor %}
-    </div>
+  {% for group, items in form.fieldsets %}
+    {% render_fieldset form items heading=group %}
   {% endfor %}
 
   {% if form.custom_fields %}

+ 10 - 0
netbox/utilities/forms/rendering.py

@@ -0,0 +1,10 @@
+__all__ = (
+    'InlineFields',
+)
+
+
+class InlineFields:
+
+    def __init__(self, *field_names, label=None):
+        self.field_names = field_names
+        self.label = label

+ 26 - 0
netbox/utilities/templates/form_helpers/render_fieldset.html

@@ -0,0 +1,26 @@
+{% load i18n %}
+{% load form_helpers %}
+<div class="field-group mb-5">
+  {% if heading %}
+    <div class="row">
+      <h5 class="col-9 offset-3">{{ heading }}</h5>
+    </div>
+  {% endif %}
+  {% for layout, title, items in rows %}
+    {% if layout == 'field' %}
+      {# Single form field #}
+      {% render_field items.0 %}
+    {% elif layout == 'inline' %}
+      {# Multiple form fields on the same line #}
+      <div class="row mb-3">
+        <label class="col col-form-label text-lg-end">{{ title|default:'' }}</label>
+        {% for field in items %}
+          <div class="col mb-1">
+            {{ field }}
+            <div class="form-text">{% trans field.label %}</div>
+          </div>
+        {% endfor %}
+      </div>
+    {% endif %}
+  {% endfor %}
+</div>

+ 24 - 0
netbox/utilities/templatetags/form_helpers.py

@@ -1,5 +1,7 @@
 from django import template
 
+from utilities.forms.rendering import InlineFields
+
 __all__ = (
     'getfield',
     'render_custom_fields',
@@ -45,6 +47,28 @@ def widget_type(field):
 # Inclusion tags
 #
 
+@register.inclusion_tag('form_helpers/render_fieldset.html')
+def render_fieldset(form, fieldset, heading=None):
+    """
+    Render a group set of fields.
+    """
+    rows = []
+    for item in fieldset:
+        if type(item) is InlineFields:
+            rows.append(
+                ('inline', item.label, [form[name] for name in item.field_names])
+            )
+        else:
+            rows.append(
+                ('field', None, [form[item]])
+            )
+
+    return {
+        'heading': heading,
+        'rows': rows,
+    }
+
+
 @register.inclusion_tag('form_helpers/render_field.html')
 def render_field(field, bulk_nullable=False, label=None):
     """