Hide RackType-defined fields on RackForm when a rack type is set

This commit is contained in:
Jeremy Stretch 2024-07-15 21:36:10 -04:00
parent 5811f9ecad
commit 4544aaa314
3 changed files with 35 additions and 25 deletions

View File

@ -11,7 +11,7 @@ from extras.models import ConfigTemplate
from ipam.models import ASN, IPAddress, VLAN, VLANGroup, VRF from ipam.models import ASN, IPAddress, VLAN, VLANGroup, VRF
from netbox.forms import NetBoxModelForm from netbox.forms import NetBoxModelForm
from tenancy.forms import TenancyForm from tenancy.forms import TenancyForm
from utilities.forms import add_blank_choice from utilities.forms import add_blank_choice, get_field_value
from utilities.forms.fields import ( from utilities.forms.fields import (
CommentField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, JSONField, NumericArrayField, SlugField, CommentField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, JSONField, NumericArrayField, SlugField,
) )
@ -252,22 +252,23 @@ class RackForm(TenancyForm, NetBoxModelForm):
rack_type = DynamicModelChoiceField( rack_type = DynamicModelChoiceField(
label=_('Rack Type'), label=_('Rack Type'),
queryset=RackType.objects.all(), queryset=RackType.objects.all(),
required=False required=False,
help_text=_("Select a pre-defined rack type, or set physical characteristics below.")
) )
comments = CommentField() comments = CommentField()
fieldsets = ( fieldsets = (
FieldSet('site', 'location', 'name', 'status', 'role', 'description', 'tags', name=_('Rack')), FieldSet('site', 'location', 'name', 'status', 'role', 'rack_type', 'description', 'tags', name=_('Rack')),
FieldSet('facility_id', 'serial', 'asset_tag', name=_('Inventory Control')), FieldSet('facility_id', 'serial', 'asset_tag', name=_('Inventory Control')),
FieldSet('tenant_group', 'tenant', name=_('Tenancy')), FieldSet('tenant_group', 'tenant', name=_('Tenancy')),
FieldSet(
'rack_type', 'form_factor', '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', name=_('Dimensions')
),
) )
# Fields which cannot be set locally if a RackType is assigned
RACKTYPE_FIELDS = [
'form_factor', 'width', 'u_height', 'starting_unit', 'desc_units', 'outer_width', 'outer_depth', 'outer_unit',
'mounting_depth', 'weight', 'weight_unit', 'max_weight'
]
class Meta: class Meta:
model = Rack model = Rack
fields = [ fields = [
@ -280,9 +281,27 @@ class RackForm(TenancyForm, NetBoxModelForm):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
if self.instance.pk and self.instance.rack_type: # Mimic HTMXSelect()
for field_name in self.instance.rack_type.RACK_FIELDS: self.fields['rack_type'].widget.attrs.update({
self.fields[field_name].disabled = True 'hx-get': '.',
'hx-include': '#form_fields',
'hx-target': '#form_fields',
})
# Omit RackType-defined fields if rack_type is set
if get_field_value(self, 'rack_type'):
for field_name in self.RACKTYPE_FIELDS:
del self.fields[field_name]
else:
self.fieldsets = (
*self.fieldsets,
FieldSet(
'form_factor', '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', name=_('Dimensions')
),
)
class RackReservationForm(TenancyForm, NetBoxModelForm): class RackReservationForm(TenancyForm, NetBoxModelForm):

View File

@ -126,12 +126,6 @@ class RackType(RackBase):
Devices are housed within Racks. Each rack has a defined height measured in rack units, and a front and rear face. Devices are housed within Racks. Each rack has a defined height measured in rack units, and a front and rear face.
Each Rack is assigned to a Site and (optionally) a Location. Each Rack is assigned to a Site and (optionally) a Location.
""" """
RACK_FIELDS = [
'type', 'width', 'u_height', 'starting_unit', 'desc_units', 'outer_width',
'outer_depth', 'outer_unit', 'weight', 'weight_unit', 'max_weight',
'mounting_depth'
]
manufacturer = models.ForeignKey( manufacturer = models.ForeignKey(
to='dcim.Manufacturer', to='dcim.Manufacturer',
on_delete=models.PROTECT, on_delete=models.PROTECT,
@ -401,13 +395,6 @@ class Rack(ContactsMixin, ImageAttachmentsMixin, RackBase):
'location': _("Location must be from the same site, {site}.").format(site=self.site) 'location': _("Location must be from the same site, {site}.").format(site=self.site)
}) })
if self.rack_type:
for field_name in self.rack_type.RACK_FIELDS:
if getattr(self, field_name, None) != getattr(self.rack_type, field_name, None):
raise ValidationError({
field_name: _("Cannot modify field {field_name} if rack_type set.").format(field_name=field_name)
})
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
if (not self.pk) and self.rack_type: if (not self.pk) and self.rack_type:
self.form_factor = self.rack_type.form_factor self.form_factor = self.rack_type.form_factor

View File

@ -43,6 +43,10 @@
<th scope="row">{% trans "Status" %}</th> <th scope="row">{% trans "Status" %}</th>
<td>{% badge object.get_status_display bg_color=object.get_status_color %}</td> <td>{% badge object.get_status_display bg_color=object.get_status_color %}</td>
</tr> </tr>
<tr>
<th scope="row">{% trans "Rack Type" %}</th>
<td>{{ object.rack_type|linkify|placeholder }}</td>
</tr>
<tr> <tr>
<th scope="row">{% trans "Role" %}</th> <th scope="row">{% trans "Role" %}</th>
<td>{{ object.role|linkify|placeholder }}</td> <td>{{ object.role|linkify|placeholder }}</td>