12826 add tests and fixes

This commit is contained in:
Arthur Hanson 2024-06-25 11:11:37 -07:00
parent fc1ce31b00
commit 811c1bdfaa
11 changed files with 360 additions and 43 deletions

View File

@ -3,7 +3,7 @@ from rest_framework import serializers
from dcim.choices import *
from dcim.constants import *
from dcim.models import Rack, RackReservation, RackRole
from dcim.models import Rack, RackReservation, RackRole, RackType
from netbox.api.fields import ChoiceField, RelatedObjectCountField
from netbox.api.serializers import NetBoxModelSerializer
from netbox.config import ConfigItem
@ -41,7 +41,7 @@ class RackTypeSerializer(NetBoxModelSerializer):
weight_unit = ChoiceField(choices=WeightUnitChoices, allow_blank=True, required=False, allow_null=True)
class Meta:
model = Rack
model = RackType
fields = [
'id', 'url', 'display_url', 'display', 'name',
'type', 'width', 'u_height', 'starting_unit', 'weight', 'max_weight',

View File

@ -297,19 +297,9 @@ class RackTypeFilterSet(NetBoxModelFilterSet):
width = django_filters.MultipleChoiceFilter(
choices=RackWidthChoices
)
role_id = django_filters.ModelMultipleChoiceFilter(
queryset=RackRole.objects.all(),
label=_('Role (ID)'),
)
role = django_filters.ModelMultipleChoiceFilter(
field_name='role__slug',
queryset=RackRole.objects.all(),
to_field_name='slug',
label=_('Role (slug)'),
)
class Meta:
model = Rack
model = RackType
fields = (
'id', 'name', 'u_height', 'starting_unit', 'desc_units', 'outer_width',
'outer_depth', 'outer_unit', 'mounting_depth', 'weight', 'max_weight', 'weight_unit', 'description',

View File

@ -241,11 +241,10 @@ class RackRoleFilterForm(NetBoxModelFilterSetForm):
class RackTypeFilterForm(NetBoxModelFilterSetForm):
model = Rack
model = RackType
fieldsets = (
FieldSet('q', 'filter_id', 'tag'),
FieldSet('role_id', name=_('Function')),
FieldSet('type', 'width', 'serial', name=_('Hardware')),
FieldSet('type', 'width', name=_('Hardware')),
FieldSet('weight', 'max_weight', 'weight_unit', name=_('Weight')),
)
selector_fields = ('filter_id', 'q',)
@ -259,16 +258,6 @@ class RackTypeFilterForm(NetBoxModelFilterSetForm):
choices=RackWidthChoices,
required=False
)
role_id = DynamicModelMultipleChoiceField(
queryset=RackRole.objects.all(),
required=False,
null_option='None',
label=_('Role')
)
serial = forms.CharField(
label=_('Serial'),
required=False
)
tag = TagFilterField(model)
weight = forms.DecimalField(
label=_('Weight'),

View File

@ -120,7 +120,7 @@ class RackType(ImageAttachmentsMixin, PrimaryModel, WeightMixin):
)
clone_fields = (
'role', 'type', 'width', 'u_height', 'desc_units', 'outer_width',
'type', 'width', 'u_height', 'desc_units', 'outer_width',
'outer_depth', 'outer_unit', 'mounting_depth', 'weight', 'max_weight', 'weight_unit',
)
prerequisite_models = (
@ -172,21 +172,6 @@ class RackType(ImageAttachmentsMixin, PrimaryModel, WeightMixin):
return drange(decimal.Decimal(self.starting_unit), self.u_height + self.starting_unit, 0.5)
return drange(self.u_height + decimal.Decimal(0.5) + self.starting_unit - 1, 0.5 + self.starting_unit - 1, -0.5)
@cached_property
def total_weight(self):
total_weight = sum(
device.device_type._abs_weight
for device in self.devices.exclude(device_type___abs_weight__isnull=True).prefetch_related('device_type')
)
total_weight += sum(
module.module_type._abs_weight
for module in Module.objects.filter(device__rack=self)
.exclude(module_type___abs_weight__isnull=True)
.prefetch_related('module_type')
)
if self._abs_weight:
total_weight += self._abs_weight
return round(total_weight / 1000, 2)
#
# Racks

View File

@ -242,6 +242,19 @@ class PowerPortIndex(SearchIndex):
display_attrs = ('device', 'label', 'type', 'description')
@register_search
class RackTypeIndex(SearchIndex):
model = models.RackType
fields = (
('name', 100),
('description', 500),
('comments', 5000),
)
display_attrs = (
'site', 'description',
)
@register_search
class RackIndex(SearchIndex):
model = models.Rack

View File

@ -274,6 +274,36 @@ class RackRoleTest(APIViewTestCases.APIViewTestCase):
RackRole.objects.bulk_create(rack_roles)
class RackTypeTest(APIViewTestCases.APIViewTestCase):
model = RackType
brief_fields = ['description', 'display', 'id', 'name', 'url']
bulk_update_data = {
'description': 'new description',
}
@classmethod
def setUpTestData(cls):
racks = (
RackType(name='Rack 1'),
RackType(name='Rack 2'),
RackType(name='Rack 3'),
)
RackType.objects.bulk_create(racks)
cls.create_data = [
{
'name': 'Test Rack 4',
},
{
'name': 'Test Rack 5',
},
{
'name': 'Test Rack 6',
},
]
class RackTest(APIViewTestCases.APIViewTestCase):
model = Rack
brief_fields = ['description', 'device_count', 'display', 'id', 'name', 'url']

View File

@ -468,6 +468,121 @@ class RackRoleTestCase(TestCase, ChangeLoggedFilterSetTests):
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
class RackTypeTestCase(TestCase, ChangeLoggedFilterSetTests):
queryset = RackType.objects.all()
filterset = RackTypeFilterSet
@classmethod
def setUpTestData(cls):
racks = (
RackType(
name='Rack 1',
type=RackTypeChoices.TYPE_2POST,
width=RackWidthChoices.WIDTH_19IN,
u_height=42,
desc_units=False,
outer_width=100,
outer_depth=100,
outer_unit=RackDimensionUnitChoices.UNIT_MILLIMETER,
weight=10,
max_weight=1000,
weight_unit=WeightUnitChoices.UNIT_POUND,
description='foobar1'
),
RackType(
name='Rack 2',
type=RackTypeChoices.TYPE_4POST,
width=RackWidthChoices.WIDTH_21IN,
u_height=43,
desc_units=False,
outer_width=200,
outer_depth=200,
outer_unit=RackDimensionUnitChoices.UNIT_MILLIMETER,
weight=20,
max_weight=2000,
weight_unit=WeightUnitChoices.UNIT_POUND,
description='foobar2'
),
RackType(
name='Rack 3',
type=RackTypeChoices.TYPE_CABINET,
width=RackWidthChoices.WIDTH_23IN,
u_height=44,
desc_units=True,
outer_width=300,
outer_depth=300,
outer_unit=RackDimensionUnitChoices.UNIT_INCH,
weight=30,
max_weight=3000,
weight_unit=WeightUnitChoices.UNIT_KILOGRAM,
description='foobar3'
),
)
RackType.objects.bulk_create(racks)
def test_q(self):
params = {'q': 'foobar1'}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1)
def test_name(self):
params = {'name': ['Rack 1', 'Rack 2']}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
def test_description(self):
params = {'description': ['foobar1', 'foobar2']}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
def test_type(self):
params = {'type': [RackTypeChoices.TYPE_2POST, RackTypeChoices.TYPE_4POST]}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
def test_width(self):
params = {'width': [RackWidthChoices.WIDTH_19IN, RackWidthChoices.WIDTH_21IN]}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
def test_u_height(self):
params = {'u_height': [42, 43]}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
def test_starting_unit(self):
params = {'starting_unit': [1]}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3)
params = {'starting_unit': [2]}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 0)
def test_desc_units(self):
params = {'desc_units': 'true'}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1)
params = {'desc_units': 'false'}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
def test_outer_width(self):
params = {'outer_width': [100, 200]}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
def test_outer_depth(self):
params = {'outer_depth': [100, 200]}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
def test_outer_unit(self):
self.assertEqual(Rack.objects.filter(outer_unit__isnull=False).count(), 3)
params = {'outer_unit': RackDimensionUnitChoices.UNIT_MILLIMETER}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
def test_weight(self):
params = {'weight': [10, 20]}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
def test_max_weight(self):
params = {'max_weight': [1000, 2000]}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
def test_weight_unit(self):
params = {'weight_unit': WeightUnitChoices.UNIT_POUND}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
class RackTestCase(TestCase, ChangeLoggedFilterSetTests):
queryset = Rack.objects.all()
filterset = RackFilterSet

View File

@ -74,6 +74,17 @@ class LocationTestCase(TestCase):
self.assertEqual(PowerPanel.objects.get(pk=powerpanel1.pk).site, site_b)
class RackTypeTestCase(TestCase):
@classmethod
def setUpTestData(cls):
RackType.objects.create(
name='Rack 1',
u_height=42
)
class RackTestCase(TestCase):
@classmethod

View File

@ -336,6 +336,67 @@ class RackReservationTestCase(ViewTestCases.PrimaryObjectViewTestCase):
}
class RackTypeTestCase(ViewTestCases.PrimaryObjectViewTestCase):
model = RackType
@classmethod
def setUpTestData(cls):
racks = (
Rack(name='Rack 1'),
Rack(name='Rack 2'),
Rack(name='Rack 3'),
)
RackType.objects.bulk_create(racks)
tags = create_tags('Alpha', 'Bravo', 'Charlie')
cls.form_data = {
'name': 'Rack X',
'type': RackTypeChoices.TYPE_CABINET,
'width': RackWidthChoices.WIDTH_19IN,
'u_height': 48,
'desc_units': False,
'outer_width': 500,
'outer_depth': 500,
'outer_unit': RackDimensionUnitChoices.UNIT_MILLIMETER,
'starting_unit': 1,
'weight': 100,
'max_weight': 2000,
'weight_unit': WeightUnitChoices.UNIT_POUND,
'comments': 'Some comments',
'tags': [t.pk for t in tags],
}
cls.csv_data = (
"name,width,u_height,weight,max_weight,weight_unit",
",Rack 4,19,42,100,2000,kg",
"Rack 5,19,42,100,2000,kg",
"Rack 6,19,42,100,2000,kg",
)
cls.csv_update_data = (
"id,name",
f"{racks[0].pk},Rack 7",
f"{racks[1].pk},Rack 8",
f"{racks[2].pk},Rack 9",
)
cls.bulk_edit_data = {
'type': RackTypeChoices.TYPE_4POST,
'width': RackWidthChoices.WIDTH_23IN,
'u_height': 49,
'desc_units': True,
'outer_width': 30,
'outer_depth': 30,
'outer_unit': RackDimensionUnitChoices.UNIT_INCH,
'weight': 200,
'max_weight': 4000,
'weight_unit': WeightUnitChoices.UNIT_POUND,
'comments': 'New comments',
}
class RackTestCase(ViewTestCases.PrimaryObjectViewTestCase):
model = Rack

View File

@ -592,7 +592,7 @@ class RackTypeListView(generic.ObjectListView):
@register_model_view(RackType)
class RackTypeView(GetRelatedModelsMixin, generic.ObjectView):
queryset = Rack.objects.prefetch_related('role')
queryset = RackType.objects.all()
@register_model_view(RackType, 'edit')

View File

@ -0,0 +1,123 @@
{% extends 'dcim/rack/base.html' %}
{% load buttons %}
{% load helpers %}
{% load static %}
{% load plugins %}
{% load i18n %}
{% load mptt %}
{% block content %}
<div class="row">
<div class="col col-12 col-xl-5">
<div class="card">
<h5 class="card-header">{% trans "Rack" %}</h5>
<table class="table table-hover attr-table">
<tr>
<th scope="row">{% trans "Description" %}</th>
<td>{{ object.description|placeholder }}</td>
</tr>
</table>
</div>
<div class="card">
<h5 class="card-header">{% trans "Dimensions" %}</h5>
<table class="table table-hover attr-table">
<tr>
<th scope="row">{% trans "Type" %}</th>
<td>
{% if object.type %}
{{ object.get_type_display }}
{% else %}
{{ ''|placeholder }}
{% endif %}
</td>
</tr>
<tr>
<th scope="row">{% trans "Width" %}</th>
<td>{{ object.get_width_display }}</td>
</tr>
<tr>
<th scope="row">{% trans "Height" %}</th>
<td>{{ object.u_height }}U ({% if object.desc_units %}{% trans "descending" %}{% else %}{% trans "ascending" %}{% endif %})</td>
</tr>
<tr>
<th scope="row">{% trans "Starting Unit" %}</th>
<td>
{{ object.starting_unit }}
</td>
</tr>
<tr>
<th scope="row">{% trans "Outer Width" %}</th>
<td>
{% if object.outer_width %}
{{ object.outer_width }} {{ object.get_outer_unit_display }}
{% else %}
{{ ''|placeholder }}
{% endif %}
</td>
</tr>
<tr>
<th scope="row">{% trans "Outer Depth" %}</th>
<td>
{% if object.outer_depth %}
{{ object.outer_depth }} {{ object.get_outer_unit_display }}
{% else %}
{{ ''|placeholder }}
{% endif %}
</td>
</tr>
<tr>
<th scope="row">{% trans "Mounting Depth" %}</th>
<td>
{% if object.mounting_depth %}
{{ object.mounting_depth }} {% trans "Millimeters" %}
{% else %}
{{ ''|placeholder }}
{% endif %}
</td>
</tr>
<tr>
<th scope="row">{% trans "Rack Weight" %}</th>
<td>
{% if object.weight %}
{{ object.weight|floatformat }} {{ object.get_weight_unit_display }}
{% else %}
{{ ''|placeholder }}
{% endif %}
</td>
</tr>
<tr>
<th scope="row">{% trans "Maximum Weight" %}</th>
<td>
{% if object.max_weight %}
{{ object.max_weight }} {{ object.get_weight_unit_display }}
{% else %}
{{ ''|placeholder }}
{% endif %}
</td>
</tr>
</table>
</div>
{% include 'inc/panels/custom_fields.html' %}
{% include 'inc/panels/tags.html' %}
{% include 'inc/panels/comments.html' %}
{% include 'inc/panels/image_attachments.html' %}
{% plugin_left_page object %}
</div>
<div class="col col-12 col-xl-7">
<div class="text-end mb-4">
<select class="btn btn-outline-secondary no-ts rack-view">
<option value="images-and-labels" selected="selected">{% trans "Images and Labels" %}</option>
<option value="images-only">{% trans "Images only" %}</option>
<option value="labels-only">{% trans "Labels only" %}</option>
</select>
</div>
{% include 'inc/panels/related_objects.html' %}
{% plugin_right_page object %}
</div>
</div>
<div class="row">
<div class="col col-md-12">
{% plugin_full_width_page object %}
</div>
</div>
{% endblock %}