diff --git a/netbox/dcim/forms/model_forms.py b/netbox/dcim/forms/model_forms.py index 92740ec45..44c3bb40a 100644 --- a/netbox/dcim/forms/model_forms.py +++ b/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 = [ diff --git a/netbox/dcim/views.py b/netbox/dcim/views.py index 93e5f04dc..b447ae579 100644 --- a/netbox/dcim/views.py +++ b/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') diff --git a/netbox/templates/dcim/rack_edit.html b/netbox/templates/dcim/rack_edit.html deleted file mode 100644 index 21bc8303d..000000000 --- a/netbox/templates/dcim/rack_edit.html +++ /dev/null @@ -1,90 +0,0 @@ -{% extends 'generic/object_edit.html' %} -{% load form_helpers %} -{% load i18n %} - -{% block form %} -
-
-
{% trans "Rack" %}
-
- {% 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 %} -
- -
-
-
{% trans "Inventory Control" %}
-
- {% render_field form.facility_id %} - {% render_field form.serial %} - {% render_field form.asset_tag %} -
- -
-
-
{% trans "Tenancy" %}
-
- {% render_field form.tenant_group %} - {% render_field form.tenant %} -
- -
-
-
{% trans "Dimensions" %}
-
- {% render_field form.type %} - {% render_field form.width %} - {% render_field form.starting_unit %} - {% render_field form.u_height %} -
- -
- {{ form.outer_width }} -
{% trans "Width" %}
-
-
- {{ form.outer_depth }} -
{% trans "Depth" %}
-
-
- {{ form.outer_unit }} -
{% trans "Unit" %}
-
-
-
- -
- {{ form.weight }} -
{% trans "Weight" %}
-
-
- {{ form.max_weight }} -
{% trans "Maximum Weight" %}
-
-
- {{ form.weight_unit }} -
{% trans "Unit" %}
-
-
- {% render_field form.mounting_depth %} - {% render_field form.desc_units %} -
- - {% if form.custom_fields %} -
-
-
{% trans "Custom Fields" %}
-
- {% render_custom_fields form %} -
- {% endif %} - -
- {% render_field form.comments %} -
-{% endblock %} diff --git a/netbox/templates/htmx/form.html b/netbox/templates/htmx/form.html index 3aafc2a21..0bfcb00ca 100644 --- a/netbox/templates/htmx/form.html +++ b/netbox/templates/htmx/form.html @@ -9,21 +9,8 @@ {% endfor %} {# Render grouped fields according to Form #} - {% for group, fields in form.fieldsets %} -
- {% if group %} -
-
{{ group }}
-
- {% 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 %} -
+ {% for group, items in form.fieldsets %} + {% render_fieldset form items heading=group %} {% endfor %} {% if form.custom_fields %} diff --git a/netbox/utilities/forms/rendering.py b/netbox/utilities/forms/rendering.py new file mode 100644 index 000000000..498b1a2ce --- /dev/null +++ b/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 diff --git a/netbox/utilities/templates/form_helpers/render_fieldset.html b/netbox/utilities/templates/form_helpers/render_fieldset.html new file mode 100644 index 000000000..718a8f6a0 --- /dev/null +++ b/netbox/utilities/templates/form_helpers/render_fieldset.html @@ -0,0 +1,26 @@ +{% load i18n %} +{% load form_helpers %} +
+ {% if heading %} +
+
{{ heading }}
+
+ {% 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 #} +
+ + {% for field in items %} +
+ {{ field }} +
{% trans field.label %}
+
+ {% endfor %} +
+ {% endif %} + {% endfor %} +
diff --git a/netbox/utilities/templatetags/form_helpers.py b/netbox/utilities/templatetags/form_helpers.py index f4fd8b819..3f60627b4 100644 --- a/netbox/utilities/templatetags/form_helpers.py +++ b/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): """