mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-27 02:48:38 -06:00
18245 add forms, views, fitlersets, api
This commit is contained in:
parent
3724c6c5b2
commit
7c8862cb1e
@ -7,6 +7,7 @@ from dcim import models
|
||||
__all__ = (
|
||||
'NestedDeviceBaySerializer',
|
||||
'NestedDeviceSerializer',
|
||||
'NestedDeviceRoleGroupSerializer',
|
||||
'NestedInterfaceSerializer',
|
||||
'NestedInterfaceTemplateSerializer',
|
||||
'NestedLocationSerializer',
|
||||
@ -52,6 +53,18 @@ class NestedLocationSerializer(WritableNestedSerializer):
|
||||
fields = ['id', 'url', 'display_url', 'display', 'name', 'slug', 'rack_count', '_depth']
|
||||
|
||||
|
||||
@extend_schema_serializer(
|
||||
exclude_fields=('tenant_count',),
|
||||
)
|
||||
class NestedDeviceRoleGroupSerializer(WritableNestedSerializer):
|
||||
role_count = serializers.IntegerField(read_only=True)
|
||||
_depth = serializers.IntegerField(source='level', read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = models.DeviceRoleGroup
|
||||
fields = ['id', 'url', 'display_url', 'display', 'name', 'slug', 'role_count', '_depth']
|
||||
|
||||
|
||||
class NestedDeviceSerializer(WritableNestedSerializer):
|
||||
|
||||
class Meta:
|
||||
|
@ -1,14 +1,31 @@
|
||||
from dcim.models import DeviceRole, InventoryItemRole
|
||||
from rest_framework import serializers
|
||||
|
||||
from dcim.models import DeviceRole, DeviceRoleGroup, InventoryItemRole
|
||||
from extras.api.serializers_.configtemplates import ConfigTemplateSerializer
|
||||
from netbox.api.fields import RelatedObjectCountField
|
||||
from netbox.api.serializers import NetBoxModelSerializer
|
||||
from netbox.api.serializers import NestedGroupModelSerializer, NetBoxModelSerializer
|
||||
from .nested import NestedDeviceRoleGroupSerializer
|
||||
|
||||
__all__ = (
|
||||
'DeviceRoleSerializer',
|
||||
'DeviceRoleGroupSerializer',
|
||||
'InventoryItemRoleSerializer',
|
||||
)
|
||||
|
||||
|
||||
class DeviceRoleGroupSerializer(NestedGroupModelSerializer):
|
||||
parent = NestedDeviceRoleGroupSerializer(required=False, allow_null=True)
|
||||
tenant_count = serializers.IntegerField(read_only=True, default=0)
|
||||
|
||||
class Meta:
|
||||
model = DeviceRoleGroup
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'name', 'slug', 'parent', 'description', 'tags', 'custom_fields',
|
||||
'created', 'last_updated', 'role_count', 'comments', '_depth',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'name', 'slug', 'description', 'role_count', '_depth')
|
||||
|
||||
|
||||
class DeviceRoleSerializer(NetBoxModelSerializer):
|
||||
config_template = ConfigTemplateSerializer(nested=True, required=False, allow_null=True, default=None)
|
||||
|
||||
|
@ -36,6 +36,7 @@ router.register('inventory-item-templates', views.InventoryItemTemplateViewSet)
|
||||
|
||||
# Device/modules
|
||||
router.register('device-roles', views.DeviceRoleViewSet)
|
||||
router.register('device-role-groups', views.DeviceRoleGroupViewSet)
|
||||
router.register('platforms', views.PlatformViewSet)
|
||||
router.register('devices', views.DeviceViewSet)
|
||||
router.register('virtual-device-contexts', views.VirtualDeviceContextViewSet)
|
||||
|
@ -343,6 +343,18 @@ class InventoryItemTemplateViewSet(MPTTLockedMixin, NetBoxModelViewSet):
|
||||
# Device roles
|
||||
#
|
||||
|
||||
class DeviceRoleGroupViewSet(MPTTLockedMixin, NetBoxModelViewSet):
|
||||
queryset = DeviceRoleGroup.objects.add_related_count(
|
||||
DeviceRoleGroup.objects.all(),
|
||||
DeviceRole,
|
||||
'group',
|
||||
'role_count',
|
||||
cumulative=True
|
||||
)
|
||||
serializer_class = serializers.DeviceRoleGroupSerializer
|
||||
filterset_class = filtersets.DeviceRoleGroupFilterSet
|
||||
|
||||
|
||||
class DeviceRoleViewSet(NetBoxModelViewSet):
|
||||
queryset = DeviceRole.objects.all()
|
||||
serializer_class = serializers.DeviceRoleSerializer
|
||||
|
@ -43,6 +43,7 @@ __all__ = (
|
||||
'DeviceBayTemplateFilterSet',
|
||||
'DeviceFilterSet',
|
||||
'DeviceRoleFilterSet',
|
||||
'DeviceRoleGroupFilterSet',
|
||||
'DeviceTypeFilterSet',
|
||||
'FrontPortFilterSet',
|
||||
'FrontPortTemplateFilterSet',
|
||||
@ -917,6 +918,36 @@ class InventoryItemTemplateFilterSet(ChangeLoggedModelFilterSet, DeviceTypeCompo
|
||||
return queryset.filter(qs_filter)
|
||||
|
||||
|
||||
class DeviceRoleGroupFilterSet(NestedGroupModelFilterSet):
|
||||
parent_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=DeviceRoleGroup.objects.all(),
|
||||
label=_('Parent device role group (ID)'),
|
||||
)
|
||||
parent = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='parent__slug',
|
||||
queryset=DeviceRoleGroup.objects.all(),
|
||||
to_field_name='slug',
|
||||
label=_('Parent device role group (slug)'),
|
||||
)
|
||||
ancestor_id = TreeNodeMultipleChoiceFilter(
|
||||
queryset=DeviceRoleGroup.objects.all(),
|
||||
field_name='parent',
|
||||
lookup_expr='in',
|
||||
label=_('Device role group (ID)'),
|
||||
)
|
||||
ancestor = TreeNodeMultipleChoiceFilter(
|
||||
queryset=DeviceRoleGroup.objects.all(),
|
||||
field_name='parent',
|
||||
lookup_expr='in',
|
||||
to_field_name='slug',
|
||||
label=_('Device role group (slug)'),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = DeviceRoleGroup
|
||||
fields = ('id', 'name', 'slug', 'description')
|
||||
|
||||
|
||||
class DeviceRoleFilterSet(OrganizationalModelFilterSet):
|
||||
config_template_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=ConfigTemplate.objects.all(),
|
||||
|
@ -31,6 +31,7 @@ __all__ = (
|
||||
'DeviceBayTemplateBulkEditForm',
|
||||
'DeviceBulkEditForm',
|
||||
'DeviceRoleBulkEditForm',
|
||||
'DeviceRoleGroupBulkEditForm',
|
||||
'DeviceTypeBulkEditForm',
|
||||
'FrontPortBulkEditForm',
|
||||
'FrontPortTemplateBulkEditForm',
|
||||
@ -611,6 +612,23 @@ class ModuleTypeBulkEditForm(NetBoxModelBulkEditForm):
|
||||
nullable_fields = ('part_number', 'weight', 'weight_unit', 'description', 'comments')
|
||||
|
||||
|
||||
class DeviceRoleGroupBulkEditForm(NetBoxModelBulkEditForm):
|
||||
parent = DynamicModelChoiceField(
|
||||
label=_('Parent'),
|
||||
queryset=DeviceRoleGroup.objects.all(),
|
||||
required=False
|
||||
)
|
||||
description = forms.CharField(
|
||||
label=_('Description'),
|
||||
max_length=200,
|
||||
required=False
|
||||
)
|
||||
comments = CommentField()
|
||||
|
||||
model = DeviceRoleGroup
|
||||
nullable_fields = ('parent', 'description', 'comments')
|
||||
|
||||
|
||||
class DeviceRoleBulkEditForm(NetBoxModelBulkEditForm):
|
||||
color = ColorField(
|
||||
label=_('Color'),
|
||||
|
@ -28,6 +28,7 @@ __all__ = (
|
||||
'DeviceBayImportForm',
|
||||
'DeviceImportForm',
|
||||
'DeviceRoleImportForm',
|
||||
'DeviceRoleGroupImportForm',
|
||||
'DeviceTypeImportForm',
|
||||
'FrontPortImportForm',
|
||||
'InterfaceImportForm',
|
||||
@ -459,6 +460,21 @@ class ModuleTypeImportForm(NetBoxModelImportForm):
|
||||
]
|
||||
|
||||
|
||||
class DeviceRoleGroupImportForm(NetBoxModelImportForm):
|
||||
parent = CSVModelChoiceField(
|
||||
label=_('Parent'),
|
||||
queryset=DeviceRoleGroup.objects.all(),
|
||||
required=False,
|
||||
to_field_name='name',
|
||||
help_text=_('Parent group')
|
||||
)
|
||||
slug = SlugField()
|
||||
|
||||
class Meta:
|
||||
model = DeviceRoleGroup
|
||||
fields = ('name', 'slug', 'parent', 'description', 'tags', 'comments')
|
||||
|
||||
|
||||
class DeviceRoleImportForm(NetBoxModelImportForm):
|
||||
config_template = CSVModelChoiceField(
|
||||
label=_('Config template'),
|
||||
|
@ -27,6 +27,7 @@ __all__ = (
|
||||
'DeviceBayFilterForm',
|
||||
'DeviceFilterForm',
|
||||
'DeviceRoleFilterForm',
|
||||
'DeviceRoleGroupFilterForm',
|
||||
'DeviceTypeFilterForm',
|
||||
'FrontPortFilterForm',
|
||||
'InterfaceConnectionFilterForm',
|
||||
@ -682,6 +683,16 @@ class ModuleTypeFilterForm(NetBoxModelFilterSetForm):
|
||||
)
|
||||
|
||||
|
||||
class DeviceRoleGroupFilterForm(NetBoxModelFilterSetForm):
|
||||
model = DeviceRoleGroup
|
||||
parent_id = DynamicModelMultipleChoiceField(
|
||||
queryset=DeviceRoleGroup.objects.all(),
|
||||
required=False,
|
||||
label=_('Parent group')
|
||||
)
|
||||
tag = TagFilterField(model)
|
||||
|
||||
|
||||
class DeviceRoleFilterForm(NetBoxModelFilterSetForm):
|
||||
model = DeviceRole
|
||||
config_template_id = DynamicModelMultipleChoiceField(
|
||||
|
@ -32,6 +32,7 @@ __all__ = (
|
||||
'DeviceBayTemplateForm',
|
||||
'DeviceForm',
|
||||
'DeviceRoleForm',
|
||||
'DeviceRoleGroupForm',
|
||||
'DeviceTypeForm',
|
||||
'DeviceVCMembershipForm',
|
||||
'FrontPortForm',
|
||||
@ -423,6 +424,26 @@ class ModuleTypeForm(NetBoxModelForm):
|
||||
]
|
||||
|
||||
|
||||
class DeviceRoleGroupForm(NetBoxModelForm):
|
||||
parent = DynamicModelChoiceField(
|
||||
label=_('Parent'),
|
||||
queryset=DeviceRoleGroup.objects.all(),
|
||||
required=False
|
||||
)
|
||||
slug = SlugField()
|
||||
comments = CommentField()
|
||||
|
||||
fieldsets = (
|
||||
FieldSet('parent', 'name', 'slug', 'description', 'tags', name=_('Device Role Group')),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = DeviceRoleGroup
|
||||
fields = [
|
||||
'parent', 'name', 'slug', 'description', 'tags', 'comments'
|
||||
]
|
||||
|
||||
|
||||
class DeviceRoleForm(NetBoxModelForm):
|
||||
config_template = DynamicModelChoiceField(
|
||||
label=_('Config template'),
|
||||
|
@ -36,6 +36,7 @@ from .mixins import RenderConfigMixin
|
||||
__all__ = (
|
||||
'Device',
|
||||
'DeviceRole',
|
||||
'DeviceRoleGroup',
|
||||
'DeviceType',
|
||||
'MACAddress',
|
||||
'Manufacturer',
|
||||
@ -471,7 +472,7 @@ class ModuleType(ImageAttachmentsMixin, PrimaryModel, WeightMixin):
|
||||
|
||||
class DeviceRoleGroup(NestedGroupModel):
|
||||
"""
|
||||
An arbitrary collection of Tenants.
|
||||
An arbitrary collection of DeviceRoles.
|
||||
"""
|
||||
name = models.CharField(
|
||||
verbose_name=_('name'),
|
||||
|
@ -75,6 +75,18 @@ class DeviceRoleIndex(SearchIndex):
|
||||
display_attrs = ('description',)
|
||||
|
||||
|
||||
@register_search
|
||||
class DeviceRoleGroupIndex(SearchIndex):
|
||||
model = models.DeviceRoleGroup
|
||||
fields = (
|
||||
('name', 100),
|
||||
('slug', 110),
|
||||
('description', 500),
|
||||
('comments', 5000),
|
||||
)
|
||||
display_attrs = ('description',)
|
||||
|
||||
|
||||
@register_search
|
||||
class DeviceTypeIndex(SearchIndex):
|
||||
model = models.DeviceType
|
||||
|
@ -24,6 +24,7 @@ __all__ = (
|
||||
'DevicePowerOutletTable',
|
||||
'DeviceRearPortTable',
|
||||
'DeviceRoleTable',
|
||||
'DeviceRoleGroupTable',
|
||||
'DeviceTable',
|
||||
'FrontPortTable',
|
||||
'InterfaceTable',
|
||||
@ -58,6 +59,32 @@ MACADDRESS_COPY_BUTTON = """
|
||||
# Device roles
|
||||
#
|
||||
|
||||
class DeviceRoleGroupTable(NetBoxTable):
|
||||
name = columns.MPTTColumn(
|
||||
verbose_name=_('Name'),
|
||||
linkify=True
|
||||
)
|
||||
role_count = columns.LinkedCountColumn(
|
||||
viewname='dcim:devicerole_list',
|
||||
url_params={'group_id': 'pk'},
|
||||
verbose_name=_('Device Roles')
|
||||
)
|
||||
tags = columns.TagColumn(
|
||||
url_name='dcim:devicerolegroup_list'
|
||||
)
|
||||
comments = columns.MarkdownColumn(
|
||||
verbose_name=_('Comments'),
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
model = models.DeviceRoleGroup
|
||||
fields = (
|
||||
'pk', 'id', 'name', 'role_count', 'description', 'comments', 'slug', 'tags', 'created',
|
||||
'last_updated', 'actions',
|
||||
)
|
||||
default_columns = ('pk', 'name', 'role_count', 'description')
|
||||
|
||||
|
||||
class DeviceRoleTable(NetBoxTable):
|
||||
name = tables.Column(
|
||||
verbose_name=_('Name'),
|
||||
|
@ -73,6 +73,9 @@ urlpatterns = [
|
||||
path('device-roles/', include(get_model_urls('dcim', 'devicerole', detail=False))),
|
||||
path('device-roles/<int:pk>/', include(get_model_urls('dcim', 'devicerole'))),
|
||||
|
||||
path('device-role-groups/', include(get_model_urls('dcim', 'devicerolegroup', detail=False))),
|
||||
path('device-role-groups/<int:pk>/', include(get_model_urls('dcim', 'devicerolegroup'))),
|
||||
|
||||
path('platforms/', include(get_model_urls('dcim', 'platform', detail=False))),
|
||||
path('platforms/<int:pk>/', include(get_model_urls('dcim', 'platform'))),
|
||||
|
||||
|
@ -1897,6 +1897,61 @@ class InventoryItemTemplateBulkDeleteView(generic.BulkDeleteView):
|
||||
table = tables.InventoryItemTemplateTable
|
||||
|
||||
|
||||
#
|
||||
# Device role groups
|
||||
#
|
||||
|
||||
@register_model_view(DeviceRoleGroup, 'list', path='', detail=False)
|
||||
class DeviceRoleGroupListView(generic.ObjectListView):
|
||||
queryset = DeviceRoleGroup.objects.all()
|
||||
filterset = filtersets.DeviceRoleGroupFilterSet
|
||||
filterset_form = forms.DeviceRoleGroupFilterForm
|
||||
table = tables.DeviceRoleGroupTable
|
||||
|
||||
|
||||
@register_model_view(DeviceRoleGroup)
|
||||
class DeviceRoleGroupView(GetRelatedModelsMixin, generic.ObjectView):
|
||||
queryset = DeviceRoleGroup.objects.all()
|
||||
|
||||
def get_extra_context(self, request, instance):
|
||||
return {
|
||||
'related_models': self.get_related_models(request, instance),
|
||||
}
|
||||
|
||||
|
||||
@register_model_view(DeviceRoleGroup, 'add', detail=False)
|
||||
@register_model_view(DeviceRoleGroup, 'edit')
|
||||
class DeviceRoleGroupEditView(generic.ObjectEditView):
|
||||
queryset = DeviceRoleGroup.objects.all()
|
||||
form = forms.DeviceRoleGroupForm
|
||||
|
||||
|
||||
@register_model_view(DeviceRoleGroup, 'delete')
|
||||
class DeviceRoleGroupDeleteView(generic.ObjectDeleteView):
|
||||
queryset = DeviceRoleGroup.objects.all()
|
||||
|
||||
|
||||
@register_model_view(DeviceRoleGroup, 'bulk_import', detail=False)
|
||||
class DeviceRoleGroupBulkImportView(generic.BulkImportView):
|
||||
queryset = DeviceRoleGroup.objects.all()
|
||||
model_form = forms.DeviceRoleGroupImportForm
|
||||
|
||||
|
||||
@register_model_view(DeviceRoleGroup, 'bulk_edit', path='edit', detail=False)
|
||||
class DeviceRoleGroupBulkEditView(generic.BulkEditView):
|
||||
queryset = DeviceRoleGroup.objects.all()
|
||||
filterset = filtersets.DeviceRoleGroupFilterSet
|
||||
table = tables.DeviceRoleGroupTable
|
||||
form = forms.DeviceRoleGroupBulkEditForm
|
||||
|
||||
|
||||
@register_model_view(DeviceRoleGroup, 'bulk_delete', path='delete', detail=False)
|
||||
class DeviceRoleGroupBulkDeleteView(generic.BulkDeleteView):
|
||||
queryset = DeviceRoleGroup.objects.all()
|
||||
filterset = filtersets.DeviceRoleGroupFilterSet
|
||||
table = tables.DeviceRoleGroupTable
|
||||
|
||||
|
||||
#
|
||||
# Device roles
|
||||
#
|
||||
|
@ -23,6 +23,7 @@ ADVISORY_LOCK_KEYS = {
|
||||
'wirelesslangroup': 105600,
|
||||
'inventoryitem': 105700,
|
||||
'inventoryitemtemplate': 105800,
|
||||
'devicerolegroup': 105900,
|
||||
|
||||
# Jobs
|
||||
'job-schedules': 110100,
|
||||
|
@ -75,6 +75,7 @@ DEVICES_MENU = Menu(
|
||||
get_model_item('dcim', 'device', _('Devices')),
|
||||
get_model_item('dcim', 'module', _('Modules')),
|
||||
get_model_item('dcim', 'devicerole', _('Device Roles')),
|
||||
get_model_item('dcim', 'devicerolegroup', _('Device Role Groups')),
|
||||
get_model_item('dcim', 'platform', _('Platforms')),
|
||||
get_model_item('dcim', 'virtualchassis', _('Virtual Chassis')),
|
||||
get_model_item('dcim', 'virtualdevicecontext', _('Virtual Device Contexts')),
|
||||
|
Loading…
Reference in New Issue
Block a user