Introduce InlineFields for rendering fields side-by-side

This commit is contained in:
Jeremy Stretch 2024-03-12 15:44:35 -04:00
parent 93c9f8cc04
commit f585c36d86
7 changed files with 79 additions and 106 deletions

View File

@ -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 = [

View File

@ -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')

View File

@ -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 %}

View File

@ -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 %}

View File

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

View File

@ -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>

View File

@ -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):
"""