mirror of
https://github.com/netbox-community/netbox.git
synced 2026-01-21 02:58:43 -06:00
12826 Add Rack Type (#16739)
* 12826 add RackType * 12826 add forms, filters, tables * 12826 add to menu * 12826 remove role * 12826 add api/serializers * 12826 add tests and fixes * 12826 fix tests * 12826 fix tests * 12826 fix tests * 12826 fix tests * 12826 add device_type to device and instantiation * 12826 test device creation * 12826 add slug * 12826 fix tests * 12826 fix slug field * 12826 prevent modification of rack fields if rack_type set * 12826 update rack fields on rack_type edit * Misc cleanup * Update model docs * Add manufacturer field to RackType * Add test for mounting_depth * Rename 'type' to 'form_factor' * Create base classes for Rack & RackType models, serializers * Hide RackType-defined fields on RackForm when a rack type is set * Establish a base filter form for Rack & RackType * Clean up RackType attr inheritance * Clean up templates --------- Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
This commit is contained in:
@@ -11,7 +11,7 @@ from extras.models import ConfigTemplate
|
||||
from ipam.models import ASN, IPAddress, VLAN, VLANGroup, VRF
|
||||
from netbox.forms import NetBoxModelForm
|
||||
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 (
|
||||
CommentField, DynamicModelChoiceField, DynamicModelMultipleChoiceField, JSONField, NumericArrayField, SlugField,
|
||||
)
|
||||
@@ -57,6 +57,7 @@ __all__ = (
|
||||
'RackForm',
|
||||
'RackReservationForm',
|
||||
'RackRoleForm',
|
||||
'RackTypeForm',
|
||||
'RearPortForm',
|
||||
'RearPortTemplateForm',
|
||||
'RegionForm',
|
||||
@@ -201,6 +202,34 @@ class RackRoleForm(NetBoxModelForm):
|
||||
]
|
||||
|
||||
|
||||
class RackTypeForm(NetBoxModelForm):
|
||||
manufacturer = DynamicModelChoiceField(
|
||||
label=_('Manufacturer'),
|
||||
queryset=Manufacturer.objects.all()
|
||||
)
|
||||
comments = CommentField()
|
||||
slug = SlugField()
|
||||
|
||||
fieldsets = (
|
||||
FieldSet('manufacturer', 'name', 'slug', 'description', 'form_factor', 'tags', name=_('Rack Type')),
|
||||
FieldSet(
|
||||
'width', 'u_height',
|
||||
InlineFields('outer_width', 'outer_depth', 'outer_unit', label=_('Outer Dimensions')),
|
||||
InlineFields('weight', 'max_weight', 'weight_unit', label=_('Weight')),
|
||||
'mounting_depth', name=_('Dimensions')
|
||||
),
|
||||
FieldSet('starting_unit', 'desc_units', name=_('Numbering')),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = RackType
|
||||
fields = [
|
||||
'manufacturer', 'name', 'slug', 'form_factor', 'width', 'u_height', 'starting_unit', 'desc_units',
|
||||
'outer_width', 'outer_depth', 'outer_unit', 'mounting_depth', 'weight', 'max_weight', 'weight_unit',
|
||||
'description', 'comments', 'tags',
|
||||
]
|
||||
|
||||
|
||||
class RackForm(TenancyForm, NetBoxModelForm):
|
||||
site = DynamicModelChoiceField(
|
||||
label=_('Site'),
|
||||
@@ -220,28 +249,54 @@ class RackForm(TenancyForm, NetBoxModelForm):
|
||||
queryset=RackRole.objects.all(),
|
||||
required=False
|
||||
)
|
||||
rack_type = DynamicModelChoiceField(
|
||||
label=_('Rack Type'),
|
||||
queryset=RackType.objects.all(),
|
||||
required=False,
|
||||
help_text=_("Select a pre-defined rack type, or set physical characteristics below.")
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
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('tenant_group', 'tenant', name=_('Tenancy')),
|
||||
FieldSet(
|
||||
'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', name=_('Dimensions')
|
||||
),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = Rack
|
||||
fields = [
|
||||
'site', 'location', 'name', 'facility_id', 'tenant_group', 'tenant', 'status', 'role', 'serial',
|
||||
'asset_tag', 'type', 'width', 'u_height', 'starting_unit', 'desc_units', 'outer_width', 'outer_depth',
|
||||
'outer_unit', 'mounting_depth', 'weight', 'max_weight', 'weight_unit', 'description', 'comments', 'tags',
|
||||
'asset_tag', 'rack_type', 'form_factor', 'width', 'u_height', 'starting_unit', 'desc_units', 'outer_width',
|
||||
'outer_depth', 'outer_unit', 'mounting_depth', 'weight', 'max_weight', 'weight_unit', 'description',
|
||||
'comments', 'tags',
|
||||
]
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
# Mimic HTMXSelect()
|
||||
self.fields['rack_type'].widget.attrs.update({
|
||||
'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 Rack.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):
|
||||
rack = DynamicModelChoiceField(
|
||||
|
||||
Reference in New Issue
Block a user