1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

Closes #450: Add 'outer_width' and 'outer_depth' fields to Rack

This commit is contained in:
Jeremy Stretch
2018-11-02 09:51:17 -04:00
parent 4ffe1866c5
commit c60c5502f6
9 changed files with 111 additions and 11 deletions

View File

@ -7,6 +7,7 @@ v2.5.0 (FUTURE)
## Enhancements
* [#450](https://github.com/digitalocean/netbox/issues/450) - Added `outer_width` and `outer_depth` fields to rack model
* [#1444](https://github.com/digitalocean/netbox/issues/1444) - Added an `asset_tag` field for racks
* [#2000](https://github.com/digitalocean/netbox/issues/2000) - Dropped support for Python 2
* [#2104](https://github.com/digitalocean/netbox/issues/2104) - Added a `status` field for racks

View File

@ -121,14 +121,15 @@ class RackSerializer(TaggitSerializer, CustomFieldModelSerializer):
role = NestedRackRoleSerializer(required=False, allow_null=True)
type = ChoiceField(choices=RACK_TYPE_CHOICES, required=False, allow_null=True)
width = ChoiceField(choices=RACK_WIDTH_CHOICES, required=False)
outer_unit = ChoiceField(choices=RACK_DIMENSION_UNIT_CHOICES, required=False)
tags = TagListSerializerField(required=False)
class Meta:
model = Rack
fields = [
'id', 'name', 'facility_id', 'display_name', 'site', 'group', 'tenant', 'status', 'role', 'serial',
'asset_tag', 'type', 'width', 'u_height', 'desc_units', 'comments', 'tags', 'custom_fields', 'created',
'last_updated',
'asset_tag', 'type', 'width', 'u_height', 'desc_units', 'outer_width', 'outer_depth', 'outer_unit',
'comments', 'tags', 'custom_fields', 'created', 'last_updated',
]
# Omit the UniqueTogetherValidator that would be automatically added to validate (group, facility_id). This
# prevents facility_id from being interpreted as a required field.
@ -504,7 +505,7 @@ class CableSerializer(ValidatedModelSerializer):
termination_a = serializers.SerializerMethodField(read_only=True)
termination_b = serializers.SerializerMethodField(read_only=True)
status = ChoiceField(choices=CONNECTION_STATUS_CHOICES, required=False)
length_unit = ChoiceField(choices=LENGTH_UNIT_CHOICES, required=False)
length_unit = ChoiceField(choices=CABLE_LENGTH_UNIT_CHOICES, required=False)
class Meta:
model = Cable

View File

@ -362,11 +362,16 @@ COMPATIBLE_TERMINATION_TYPES = {
LENGTH_UNIT_METER = 'm'
LENGTH_UNIT_CENTIMETER = 'cm'
LENGTH_UNIT_MILLIMETER = 'mm'
LENGTH_UNIT_FOOT = 'ft'
LENGTH_UNIT_INCH = 'in'
LENGTH_UNIT_CHOICES = (
CABLE_LENGTH_UNIT_CHOICES = (
(LENGTH_UNIT_METER, 'Meters'),
(LENGTH_UNIT_CENTIMETER, 'Centimeters'),
(LENGTH_UNIT_FOOT, 'Feet'),
(LENGTH_UNIT_INCH, 'Inches'),
)
RACK_DIMENSION_UNIT_CHOICES = (
(LENGTH_UNIT_MILLIMETER, 'Millimeters'),
(LENGTH_UNIT_INCH, 'Inches'),
)

View File

@ -201,7 +201,10 @@ class RackFilter(CustomFieldFilterSet, django_filters.FilterSet):
class Meta:
model = Rack
fields = ['name', 'serial', 'asset_tag', 'type', 'width', 'u_height', 'desc_units']
fields = [
'name', 'serial', 'asset_tag', 'type', 'width', 'u_height', 'desc_units', 'outer_width', 'outer_depth',
'outer_unit',
]
def search(self, queryset, name, value):
if not value.strip():

View File

@ -307,7 +307,7 @@ class RackForm(BootstrapMixin, TenancyForm, CustomFieldForm):
model = Rack
fields = [
'site', 'group', 'name', 'facility_id', 'tenant_group', 'tenant', 'status', 'role', 'serial', 'asset_tag',
'type', 'width', 'u_height', 'desc_units', 'comments', 'tags',
'type', 'width', 'u_height', 'desc_units', 'outer_width', 'outer_depth', 'outer_unit', 'comments', 'tags',
]
help_texts = {
'site': "The site at which the rack exists",
@ -368,6 +368,11 @@ class RackCSVForm(forms.ModelForm):
),
help_text='Rail-to-rail width (in inches)'
)
outer_unit = CSVChoiceField(
choices=RACK_DIMENSION_UNIT_CHOICES,
required=False,
help_text='Unit for outer dimensions'
)
class Meta:
model = Rack
@ -458,12 +463,26 @@ class RackBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldBulkEditFor
widget=BulkEditNullBooleanSelect,
label='Descending units'
)
outer_width = forms.IntegerField(
required=False,
min_value=1
)
outer_depth = forms.IntegerField(
required=False,
min_value=1
)
outer_unit = forms.ChoiceField(
choices=add_blank_choice(RACK_DIMENSION_UNIT_CHOICES),
required=False
)
comments = CommentField(
widget=SmallTextarea
)
class Meta:
nullable_fields = ['group', 'tenant', 'role', 'serial', 'asset_tag', 'comments']
nullable_fields = [
'group', 'tenant', 'role', 'serial', 'asset_tag', 'outer_width', 'outer_depth', 'outer_unit', 'comments',
]
class RackFilterForm(BootstrapMixin, CustomFieldFilterForm):
@ -1864,7 +1883,7 @@ class CableCSVForm(forms.ModelForm):
help_text='Cable type'
)
length_unit = CSVChoiceField(
choices=LENGTH_UNIT_CHOICES,
choices=CABLE_LENGTH_UNIT_CHOICES,
required=False,
help_text='Length unit'
)
@ -1962,7 +1981,7 @@ class CableBulkEditForm(BootstrapMixin, BulkEditForm):
required=False
)
length_unit = forms.ChoiceField(
choices=add_blank_choice(LENGTH_UNIT_CHOICES),
choices=add_blank_choice(CABLE_LENGTH_UNIT_CHOICES),
required=False,
initial=''
)

View File

@ -20,4 +20,19 @@ class Migration(migrations.Migration):
name='asset_tag',
field=utilities.fields.NullableCharField(blank=True, max_length=50, null=True, unique=True),
),
migrations.AddField(
model_name='rack',
name='outer_depth',
field=models.PositiveSmallIntegerField(blank=True, null=True),
),
migrations.AddField(
model_name='rack',
name='outer_unit',
field=models.CharField(blank=True, max_length=2),
),
migrations.AddField(
model_name='rack',
name='outer_width',
field=models.PositiveSmallIntegerField(blank=True, null=True),
),
]

View File

@ -510,6 +510,19 @@ class Rack(ChangeLoggedModel, CustomFieldModel):
verbose_name='Descending units',
help_text='Units are numbered top-to-bottom'
)
outer_width = models.PositiveSmallIntegerField(
blank=True,
null=True
)
outer_depth = models.PositiveSmallIntegerField(
blank=True,
null=True
)
outer_unit = models.CharField(
choices=RACK_DIMENSION_UNIT_CHOICES,
max_length=2,
blank=True
)
comments = models.TextField(
blank=True
)
@ -527,7 +540,7 @@ class Rack(ChangeLoggedModel, CustomFieldModel):
csv_headers = [
'site', 'group_name', 'name', 'facility_id', 'tenant', 'status', 'role', 'type', 'serial', 'asset_tag', 'width',
'u_height', 'desc_units', 'comments',
'u_height', 'desc_units', 'outer_width', 'outer_depth', 'outer_unit', 'comments',
]
class Meta:
@ -545,6 +558,14 @@ class Rack(ChangeLoggedModel, CustomFieldModel):
def clean(self):
# Validate outer dimensions and unit
if self.outer_width and not self.outer_unit:
raise ValidationError("Must specify a unit when setting an outer width")
if self.outer_depth and not self.outer_unit:
raise ValidationError("Must specify a unit when setting an outer depth")
if self.outer_unit and self.outer_width is None and self.outer_depth is None:
self.length_unit = ''
if self.pk:
# Validate that Rack is tall enough to house the installed Devices
top_device = Device.objects.filter(rack=self).exclude(position__isnull=True).order_by('-position').first()
@ -591,6 +612,9 @@ class Rack(ChangeLoggedModel, CustomFieldModel):
self.width,
self.u_height,
self.desc_units,
self.outer_width,
self.outer_depth,
self.outer_unit,
self.comments,
)
@ -2410,7 +2434,7 @@ class Cable(ChangeLoggedModel):
null=True
)
length_unit = models.CharField(
choices=LENGTH_UNIT_CHOICES,
choices=CABLE_LENGTH_UNIT_CHOICES,
max_length=2,
blank=True
)

View File

@ -172,6 +172,26 @@
<td>Height</td>
<td>{{ rack.u_height }}U ({% if rack.desc_units %}descending{% else %}ascending{% endif %})</td>
</tr>
<tr>
<td>Outer Width</td>
<td>
{% if rack.outer_width %}
<span>{{ rack.outer_width }}{{ rack.outer_unit }}</span>
{% else %}
<span class="text-muted">&mdash;</span>
{% endif %}
</td>
</tr>
<tr>
<td>Outer Depth</td>
<td>
{% if rack.outer_depth %}
<span>{{ rack.outer_depth }}{{ rack.outer_unit }}</span>
{% else %}
<span class="text-muted">&mdash;</span>
{% endif %}
</td>
</tr>
</table>
</div>
{% include 'inc/custom_fields_panel.html' with obj=rack %}

View File

@ -28,6 +28,18 @@
{% render_field form.type %}
{% render_field form.width %}
{% render_field form.u_height %}
<div class="form-group">
<label class="col-md-3 control-label">Outer dimensions</label>
<div class="col-md-3">
{{ form.outer_width }}
</div>
<div class="col-md-3">
{{ form.outer_depth }}
</div>
<div class="col-md-2">
{{ form.outer_unit }}
</div>
</div>
{% render_field form.desc_units %}
</div>
</div>