12826 add forms, filters, tables

This commit is contained in:
Arthur Hanson 2024-06-25 10:02:57 -07:00
parent 21e11cd78f
commit 24b957aab4
8 changed files with 352 additions and 1 deletions

View File

@ -69,6 +69,7 @@ __all__ = (
'RackFilterSet',
'RackReservationFilterSet',
'RackRoleFilterSet',
'RackTypeFilterSet',
'RearPortFilterSet',
'RearPortTemplateFilterSet',
'RegionFilterSet',
@ -289,6 +290,41 @@ class RackRoleFilterSet(OrganizationalModelFilterSet):
fields = ('id', 'name', 'slug', 'color', 'description')
class RackTypeFilterSet(NetBoxModelFilterSet):
type = django_filters.MultipleChoiceFilter(
choices=RackTypeChoices
)
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
fields = (
'id', 'name', 'u_height', 'starting_unit', 'desc_units', 'outer_width',
'outer_depth', 'outer_unit', 'mounting_depth', 'weight', 'max_weight', 'weight_unit', 'description',
)
def search(self, queryset, name, value):
if not value.strip():
return queryset
return queryset.filter(
Q(name__icontains=value) |
Q(description__icontains=value) |
Q(comments__icontains=value)
)
class RackFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ContactModelFilterSet):
region_id = TreeNodeMultipleChoiceFilter(
queryset=Region.objects.all(),

View File

@ -52,6 +52,7 @@ __all__ = (
'RackBulkEditForm',
'RackReservationBulkEditForm',
'RackRoleBulkEditForm',
'RackTypeBulkEditForm',
'RearPortBulkEditForm',
'RearPortTemplateBulkEditForm',
'RegionBulkEditForm',
@ -218,6 +219,89 @@ class RackRoleBulkEditForm(NetBoxModelBulkEditForm):
nullable_fields = ('color', 'description')
class RackTypeBulkEditForm(NetBoxModelBulkEditForm):
role = DynamicModelChoiceField(
label=_('Role'),
queryset=RackRole.objects.all(),
required=False
)
type = forms.ChoiceField(
label=_('Type'),
choices=add_blank_choice(RackTypeChoices),
required=False
)
width = forms.ChoiceField(
label=_('Width'),
choices=add_blank_choice(RackWidthChoices),
required=False
)
u_height = forms.IntegerField(
required=False,
label=_('Height (U)')
)
desc_units = forms.NullBooleanField(
required=False,
widget=BulkEditNullBooleanSelect,
label=_('Descending units')
)
outer_width = forms.IntegerField(
label=_('Outer width'),
required=False,
min_value=1
)
outer_depth = forms.IntegerField(
label=_('Outer depth'),
required=False,
min_value=1
)
outer_unit = forms.ChoiceField(
label=_('Outer unit'),
choices=add_blank_choice(RackDimensionUnitChoices),
required=False
)
mounting_depth = forms.IntegerField(
label=_('Mounting depth'),
required=False,
min_value=1
)
weight = forms.DecimalField(
label=_('Weight'),
min_value=0,
required=False
)
max_weight = forms.IntegerField(
label=_('Max weight'),
min_value=0,
required=False
)
weight_unit = forms.ChoiceField(
label=_('Weight unit'),
choices=add_blank_choice(WeightUnitChoices),
required=False,
initial=''
)
description = forms.CharField(
label=_('Description'),
max_length=200,
required=False
)
comments = CommentField()
model = Rack
fieldsets = (
FieldSet('role', 'description', name=_('Rack')),
FieldSet(
'type', 'width', 'u_height', 'desc_units', 'outer_width', 'outer_depth', 'outer_unit', 'mounting_depth',
name=_('Hardware')
),
FieldSet('weight', 'max_weight', 'weight_unit', name=_('Weight')),
)
nullable_fields = (
'role', 'outer_width', 'outer_depth', 'outer_unit', 'weight',
'max_weight', 'weight_unit', 'description', 'comments',
)
class RackBulkEditForm(NetBoxModelBulkEditForm):
region = DynamicModelChoiceField(
label=_('Region'),

View File

@ -45,6 +45,7 @@ __all__ = (
'RackImportForm',
'RackReservationImportForm',
'RackRoleImportForm',
'RackTypeImportForm',
'RearPortImportForm',
'RegionImportForm',
'SiteImportForm',
@ -179,6 +180,50 @@ class RackRoleImportForm(NetBoxModelImportForm):
}
class RackTypeImportForm(NetBoxModelImportForm):
role = CSVModelChoiceField(
label=_('Role'),
queryset=RackRole.objects.all(),
required=False,
to_field_name='name',
help_text=_('Name of assigned role')
)
type = CSVChoiceField(
label=_('Type'),
choices=RackTypeChoices,
required=False,
help_text=_('Rack type')
)
width = forms.ChoiceField(
label=_('Width'),
choices=RackWidthChoices,
help_text=_('Rail-to-rail width (in inches)')
)
outer_unit = CSVChoiceField(
label=_('Outer unit'),
choices=RackDimensionUnitChoices,
required=False,
help_text=_('Unit for outer dimensions')
)
weight_unit = CSVChoiceField(
label=_('Weight unit'),
choices=WeightUnitChoices,
required=False,
help_text=_('Unit for rack weights')
)
class Meta:
model = RackType
fields = (
'name', 'role', 'type',
'width', 'u_height', 'desc_units', 'outer_width', 'outer_depth', 'outer_unit', 'mounting_depth', 'weight',
'max_weight', 'weight_unit', 'description', 'comments', 'tags',
)
def __init__(self, data=None, *args, **kwargs):
super().__init__(data, *args, **kwargs)
class RackImportForm(NetBoxModelImportForm):
site = CSVModelChoiceField(
label=_('Site'),

View File

@ -47,6 +47,7 @@ __all__ = (
'RackElevationFilterForm',
'RackReservationFilterForm',
'RackRoleFilterForm',
'RackTypeFilterForm',
'RearPortFilterForm',
'RegionFilterForm',
'SiteFilterForm',
@ -239,6 +240,53 @@ class RackRoleFilterForm(NetBoxModelFilterSetForm):
tag = TagFilterField(model)
class RackTypeFilterForm(NetBoxModelFilterSetForm):
model = Rack
fieldsets = (
FieldSet('q', 'filter_id', 'tag'),
FieldSet('role_id', name=_('Function')),
FieldSet('type', 'width', 'serial', name=_('Hardware')),
FieldSet('weight', 'max_weight', 'weight_unit', name=_('Weight')),
)
selector_fields = ('filter_id', 'q',)
type = forms.MultipleChoiceField(
label=_('Type'),
choices=RackTypeChoices,
required=False
)
width = forms.MultipleChoiceField(
label=_('Width'),
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'),
required=False,
min_value=1
)
max_weight = forms.IntegerField(
label=_('Max weight'),
required=False,
min_value=1
)
weight_unit = forms.ChoiceField(
label=_('Weight unit'),
choices=add_blank_choice(WeightUnitChoices),
required=False
)
class RackFilterForm(TenancyFilterForm, ContactModelFilterForm, NetBoxModelFilterSetForm):
model = Rack
fieldsets = (

View File

@ -57,6 +57,7 @@ __all__ = (
'RackForm',
'RackReservationForm',
'RackRoleForm',
'RackTypeForm',
'RearPortForm',
'RearPortTemplateForm',
'RegionForm',
@ -201,6 +202,33 @@ class RackRoleForm(NetBoxModelForm):
]
class RackTypeForm(NetBoxModelForm):
role = DynamicModelChoiceField(
label=_('Role'),
queryset=RackRole.objects.all(),
required=False
)
comments = CommentField()
fieldsets = (
FieldSet('name', 'status', 'role', 'description', 'tags', name=_('Rack')),
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 = [
'name', 'role',
'type', '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'),

View File

@ -2,7 +2,7 @@ from django.utils.translation import gettext_lazy as _
import django_tables2 as tables
from django_tables2.utils import Accessor
from dcim.models import Rack, RackReservation, RackRole
from dcim.models import Rack, RackReservation, RackRole, RackType
from netbox.tables import NetBoxTable, columns
from tenancy.tables import ContactsColumnMixin, TenancyColumnsMixin
from .template_code import WEIGHT
@ -11,6 +11,7 @@ __all__ = (
'RackTable',
'RackReservationTable',
'RackRoleTable',
'RackTypeTable',
)
@ -44,6 +45,61 @@ class RackRoleTable(NetBoxTable):
default_columns = ('pk', 'name', 'rack_count', 'color', 'description')
#
# Rack Types
#
class RackTypeTable(NetBoxTable):
name = tables.Column(
verbose_name=_('Name'),
order_by=('_name',),
linkify=True
)
role = columns.ColoredLabelColumn(
verbose_name=_('Role'),
)
u_height = tables.TemplateColumn(
template_code="{{ value }}U",
verbose_name=_('Height')
)
comments = columns.MarkdownColumn(
verbose_name=_('Comments'),
)
tags = columns.TagColumn(
url_name='dcim:rack_list'
)
outer_width = tables.TemplateColumn(
template_code="{{ record.outer_width }} {{ record.outer_unit }}",
verbose_name=_('Outer Width')
)
outer_depth = tables.TemplateColumn(
template_code="{{ record.outer_depth }} {{ record.outer_unit }}",
verbose_name=_('Outer Depth')
)
weight = columns.TemplateColumn(
verbose_name=_('Weight'),
template_code=WEIGHT,
order_by=('_abs_weight', 'weight_unit')
)
max_weight = columns.TemplateColumn(
verbose_name=_('Max Weight'),
template_code=WEIGHT,
order_by=('_abs_max_weight', 'weight_unit')
)
class Meta(NetBoxTable.Meta):
model = RackType
fields = (
'pk', 'id', 'name', 'role',
'type', 'u_height', 'starting_unit', 'width', 'outer_width', 'outer_depth', 'mounting_depth',
'weight', 'max_weight', 'comments',
'description', 'tags', 'created', 'last_updated',
)
default_columns = (
'pk', 'name', 'role', 'u_height',
)
#
# Racks
#

View File

@ -63,6 +63,14 @@ urlpatterns = [
path('racks/delete/', views.RackBulkDeleteView.as_view(), name='rack_bulk_delete'),
path('racks/<int:pk>/', include(get_model_urls('dcim', 'rack'))),
# Rack Types
path('racktypes/', views.RackTypeListView.as_view(), name='racktype_list'),
path('racktypes/add/', views.RackTypeEditView.as_view(), name='racktype_add'),
path('racktypes/import/', views.RackTypeBulkImportView.as_view(), name='racktype_import'),
path('racktypes/edit/', views.RackTypeBulkEditView.as_view(), name='racktype_bulk_edit'),
path('racktypes/delete/', views.RackTypeBulkDeleteView.as_view(), name='racktype_bulk_delete'),
path('racktypes/<int:pk>/', include(get_model_urls('dcim', 'racktype'))),
# Manufacturers
path('manufacturers/', views.ManufacturerListView.as_view(), name='manufacturer_list'),
path('manufacturers/add/', views.ManufacturerEditView.as_view(), name='manufacturer_add'),

View File

@ -578,6 +578,52 @@ class RackRoleBulkDeleteView(generic.BulkDeleteView):
table = tables.RackRoleTable
#
# RackTypes
#
class RackTypeListView(generic.ObjectListView):
queryset = RackType.objects.all()
filterset = filtersets.RackTypeFilterSet
filterset_form = forms.RackTypeFilterForm
table = tables.RackTypeTable
template_name = 'dcim/racktype_list.html'
@register_model_view(RackType)
class RackTypeView(GetRelatedModelsMixin, generic.ObjectView):
queryset = Rack.objects.prefetch_related('role')
@register_model_view(RackType, 'edit')
class RackTypeEditView(generic.ObjectEditView):
queryset = RackType.objects.all()
form = forms.RackTypeForm
@register_model_view(RackType, 'delete')
class RackTypeDeleteView(generic.ObjectDeleteView):
queryset = RackType.objects.all()
class RackTypeBulkImportView(generic.BulkImportView):
queryset = RackType.objects.all()
model_form = forms.RackTypeImportForm
class RackTypeBulkEditView(generic.BulkEditView):
queryset = RackType.objects.all()
filterset = filtersets.RackTypeFilterSet
table = tables.RackTypeTable
form = forms.RackTypeBulkEditForm
class RackTypeBulkDeleteView(generic.BulkDeleteView):
queryset = RackType.objects.all()
filterset = filtersets.RackTypeFilterSet
table = tables.RackTypeTable
#
# Racks
#