From 01f791a44ee93b0342a204c5dffdf7a71c783267 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Wed, 13 Oct 2021 16:40:12 -0400 Subject: [PATCH] Add WirelessLANGroup model --- netbox/netbox/navigation_menu.py | 3 +- netbox/templates/wireless/wirelesslan.html | 10 +++ .../templates/wireless/wirelesslangroup.html | 72 ++++++++++++++++++ netbox/wireless/api/nested_serializers.py | 11 +++ netbox/wireless/api/serializers.py | 15 +++- netbox/wireless/api/urls.py | 1 + netbox/wireless/api/views.py | 12 +++ netbox/wireless/filtersets.py | 18 ++++- netbox/wireless/forms/bulk_edit.py | 25 ++++++- netbox/wireless/forms/bulk_import.py | 25 ++++++- netbox/wireless/forms/filtersets.py | 30 +++++++- netbox/wireless/forms/models.py | 27 ++++++- netbox/wireless/graphql/schema.py | 6 ++ netbox/wireless/graphql/types.py | 9 +++ netbox/wireless/migrations/0001_wireless.py | 25 ++++++- netbox/wireless/models.py | 49 ++++++++++++- netbox/wireless/tables.py | 23 +++++- netbox/wireless/urls.py | 11 +++ netbox/wireless/views.py | 73 +++++++++++++++++++ 19 files changed, 429 insertions(+), 16 deletions(-) create mode 100644 netbox/templates/wireless/wirelesslangroup.html diff --git a/netbox/netbox/navigation_menu.py b/netbox/netbox/navigation_menu.py index b3e11f6ce..7f64a2df8 100644 --- a/netbox/netbox/navigation_menu.py +++ b/netbox/netbox/navigation_menu.py @@ -168,6 +168,7 @@ CONNECTIONS_MENU = Menu( label='Connections', items=( get_model_item('dcim', 'cable', 'Cables', actions=['import']), + get_model_item('wireless', 'wirelesslink', 'Wirelesss Links', actions=['import']), MenuItem( link='dcim:interface_connections_list', link_text='Interface Connections', @@ -196,7 +197,7 @@ WIRELESS_MENU = Menu( label='Wireless', items=( get_model_item('wireless', 'wirelesslan', 'Wireless LANs'), - get_model_item('wireless', 'wirelesslink', 'Wirelesss Links', actions=['import']), + get_model_item('wireless', 'wirelesslangroup', 'Wireless LAN Groups'), ), ), ), diff --git a/netbox/templates/wireless/wirelesslan.html b/netbox/templates/wireless/wirelesslan.html index f8fabf558..f2133cd54 100644 --- a/netbox/templates/wireless/wirelesslan.html +++ b/netbox/templates/wireless/wirelesslan.html @@ -13,6 +13,16 @@ SSID {{ object.ssid }} + + Group + + {% if object.group %} + {{ object.group }} + {% else %} + None + {% endif %} + + Description {{ object.description|placeholder }} diff --git a/netbox/templates/wireless/wirelesslangroup.html b/netbox/templates/wireless/wirelesslangroup.html new file mode 100644 index 000000000..170f72eff --- /dev/null +++ b/netbox/templates/wireless/wirelesslangroup.html @@ -0,0 +1,72 @@ +{% extends 'generic/object.html' %} +{% load helpers %} +{% load plugins %} + +{% block breadcrumbs %} + {{ block.super }} + {% for group in object.get_ancestors %} + + {% endfor %} +{% endblock %} + +{% block content %} +
+
+
+
Wireless LAN Group
+
+ + + + + + + + + + + + + + + + + +
Name{{ object.name }}
Description{{ object.description|placeholder }}
Parent + {% if object.parent %} + {{ object.parent }} + {% else %} + + {% endif %} +
Wireless LANs + {{ wirelesslans_table.rows|length }} +
+
+
+ {% plugin_left_page object %} +
+
+ {% include 'inc/custom_fields_panel.html' %} + {% plugin_right_page object %} +
+
+
+
+
+
Wireless LANs
+
+ {% include 'inc/table.html' with table=wirelesslans_table %} +
+ {% if perms.wireless.add_wirelesslan %} + + {% endif %} +
+ {% include 'inc/paginator.html' with paginator=wirelesslans_table.paginator page=wirelesslans_table.page %} + {% plugin_full_width_page object %} +
+
+{% endblock %} diff --git a/netbox/wireless/api/nested_serializers.py b/netbox/wireless/api/nested_serializers.py index 5a8cf6671..e9a840bfc 100644 --- a/netbox/wireless/api/nested_serializers.py +++ b/netbox/wireless/api/nested_serializers.py @@ -5,10 +5,21 @@ from wireless.models import * __all__ = ( 'NestedWirelessLANSerializer', + 'NestedWirelessLANGroupSerializer', 'NestedWirelessLinkSerializer', ) +class NestedWirelessLANGroupSerializer(WritableNestedSerializer): + url = serializers.HyperlinkedIdentityField(view_name='wireless-api:wirelesslangroup-detail') + wirelesslan_count = serializers.IntegerField(read_only=True) + _depth = serializers.IntegerField(source='level', read_only=True) + + class Meta: + model = WirelessLANGroup + fields = ['id', 'url', 'display', 'name', 'slug', 'wirelesslan_count', '_depth'] + + class NestedWirelessLANSerializer(WritableNestedSerializer): url = serializers.HyperlinkedIdentityField(view_name='wireless-api:wirelesslan-detail') diff --git a/netbox/wireless/api/serializers.py b/netbox/wireless/api/serializers.py index 5a7330129..24395b77c 100644 --- a/netbox/wireless/api/serializers.py +++ b/netbox/wireless/api/serializers.py @@ -4,7 +4,7 @@ from dcim.choices import LinkStatusChoices from dcim.api.serializers import NestedInterfaceSerializer from ipam.api.serializers import NestedVLANSerializer from netbox.api import ChoiceField -from netbox.api.serializers import PrimaryModelSerializer +from netbox.api.serializers import NestedGroupModelSerializer, PrimaryModelSerializer from wireless.models import * from .nested_serializers import * @@ -14,6 +14,19 @@ __all__ = ( ) +class WirelessLANGroupSerializer(NestedGroupModelSerializer): + url = serializers.HyperlinkedIdentityField(view_name='wireless-api:wirelesslangroup-detail') + parent = NestedWirelessLANGroupSerializer(required=False, allow_null=True) + wirelesslan_count = serializers.IntegerField(read_only=True) + + class Meta: + model = WirelessLANGroup + fields = [ + 'id', 'url', 'display', 'name', 'slug', 'parent', 'description', 'custom_fields', 'created', 'last_updated', + 'wirelesslan_count', '_depth', + ] + + class WirelessLANSerializer(PrimaryModelSerializer): url = serializers.HyperlinkedIdentityField(view_name='wireless-api:wirelesslan-detail') vlan = NestedVLANSerializer(required=False, allow_null=True) diff --git a/netbox/wireless/api/urls.py b/netbox/wireless/api/urls.py index 431bb05f8..54f764db6 100644 --- a/netbox/wireless/api/urls.py +++ b/netbox/wireless/api/urls.py @@ -5,6 +5,7 @@ from . import views router = OrderedDefaultRouter() router.APIRootView = views.WirelessRootView +router.register('wireless-lan-groupss', views.WirelessLANGroupViewSet) router.register('wireless-lans', views.WirelessLANViewSet) router.register('wireless-links', views.WirelessLinkViewSet) diff --git a/netbox/wireless/api/views.py b/netbox/wireless/api/views.py index aa361a7f7..734f6940f 100644 --- a/netbox/wireless/api/views.py +++ b/netbox/wireless/api/views.py @@ -14,6 +14,18 @@ class WirelessRootView(APIRootView): return 'Wireless' +class WirelessLANGroupViewSet(CustomFieldModelViewSet): + queryset = WirelessLANGroup.objects.add_related_count( + WirelessLANGroup.objects.all(), + WirelessLAN, + 'group', + 'wirelesslan_count', + cumulative=True + ) + serializer_class = serializers.WirelessLANGroupSerializer + filterset_class = filtersets.WirelessLANGroupFilterSet + + class WirelessLANViewSet(CustomFieldModelViewSet): queryset = WirelessLAN.objects.prefetch_related('vlan', 'tags') serializer_class = serializers.WirelessLANSerializer diff --git a/netbox/wireless/filtersets.py b/netbox/wireless/filtersets.py index f765172dd..ac503e474 100644 --- a/netbox/wireless/filtersets.py +++ b/netbox/wireless/filtersets.py @@ -3,15 +3,31 @@ from django.db.models import Q from dcim.choices import LinkStatusChoices from extras.filters import TagFilter -from netbox.filtersets import PrimaryModelFilterSet +from netbox.filtersets import OrganizationalModelFilterSet, PrimaryModelFilterSet from .models import * __all__ = ( 'WirelessLANFilterSet', + 'WirelessLANGroupFilterSet', 'WirelessLinkFilterSet', ) +class WirelessLANGroupFilterSet(OrganizationalModelFilterSet): + parent_id = django_filters.ModelMultipleChoiceFilter( + queryset=WirelessLANGroup.objects.all() + ) + parent = django_filters.ModelMultipleChoiceFilter( + field_name='parent__slug', + queryset=WirelessLANGroup.objects.all(), + to_field_name='slug' + ) + + class Meta: + model = WirelessLANGroup + fields = ['id', 'name', 'slug', 'description'] + + class WirelessLANFilterSet(PrimaryModelFilterSet): q = django_filters.CharFilter( method='search', diff --git a/netbox/wireless/forms/bulk_edit.py b/netbox/wireless/forms/bulk_edit.py index 72af81f56..c0d5a925e 100644 --- a/netbox/wireless/forms/bulk_edit.py +++ b/netbox/wireless/forms/bulk_edit.py @@ -9,15 +9,38 @@ from wireless.models import * __all__ = ( 'WirelessLANBulkEditForm', + 'WirelessLANGroupBulkEditForm', 'WirelessLinkBulkEditForm', ) +class WirelessLANGroupBulkEditForm(BootstrapMixin, CustomFieldModelBulkEditForm): + pk = forms.ModelMultipleChoiceField( + queryset=WirelessLANGroup.objects.all(), + widget=forms.MultipleHiddenInput + ) + parent = DynamicModelChoiceField( + queryset=WirelessLANGroup.objects.all(), + required=False + ) + description = forms.CharField( + max_length=200, + required=False + ) + + class Meta: + nullable_fields = ['parent', 'description'] + + class WirelessLANBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldModelBulkEditForm): pk = forms.ModelMultipleChoiceField( queryset=WirelessLAN.objects.all(), widget=forms.MultipleHiddenInput ) + group = DynamicModelChoiceField( + queryset=WirelessLANGroup.objects.all(), + required=False + ) vlan = DynamicModelChoiceField( queryset=VLAN.objects.all(), required=False, @@ -31,7 +54,7 @@ class WirelessLANBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldMode ) class Meta: - nullable_fields = ['vlan', 'ssid', 'description'] + nullable_fields = ['ssid', 'group', 'vlan', 'description'] class WirelessLinkBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldModelBulkEditForm): diff --git a/netbox/wireless/forms/bulk_import.py b/netbox/wireless/forms/bulk_import.py index 763305c38..6b22728f6 100644 --- a/netbox/wireless/forms/bulk_import.py +++ b/netbox/wireless/forms/bulk_import.py @@ -2,16 +2,37 @@ from dcim.choices import LinkStatusChoices from dcim.models import Interface from extras.forms import CustomFieldModelCSVForm from ipam.models import VLAN -from utilities.forms import CSVChoiceField, CSVModelChoiceField +from utilities.forms import CSVChoiceField, CSVModelChoiceField, SlugField from wireless.models import * __all__ = ( 'WirelessLANCSVForm', + 'WirelessLANGroupCSVForm', 'WirelessLinkCSVForm', ) +class WirelessLANGroupCSVForm(CustomFieldModelCSVForm): + parent = CSVModelChoiceField( + queryset=WirelessLANGroup.objects.all(), + required=False, + to_field_name='name', + help_text='Parent group' + ) + slug = SlugField() + + class Meta: + model = WirelessLANGroup + fields = ('name', 'slug', 'parent', 'description') + + class WirelessLANCSVForm(CustomFieldModelCSVForm): + group = CSVModelChoiceField( + queryset=WirelessLANGroup.objects.all(), + required=False, + to_field_name='name', + help_text='Assigned group' + ) vlan = CSVModelChoiceField( queryset=VLAN.objects.all(), to_field_name='name', @@ -20,7 +41,7 @@ class WirelessLANCSVForm(CustomFieldModelCSVForm): class Meta: model = WirelessLAN - fields = ('ssid', 'description', 'vlan') + fields = ('ssid', 'group', 'description', 'vlan') class WirelessLinkCSVForm(CustomFieldModelCSVForm): diff --git a/netbox/wireless/forms/filtersets.py b/netbox/wireless/forms/filtersets.py index 6da3cd716..13aae99a5 100644 --- a/netbox/wireless/forms/filtersets.py +++ b/netbox/wireless/forms/filtersets.py @@ -3,19 +3,38 @@ from django.utils.translation import gettext as _ from dcim.choices import LinkStatusChoices from extras.forms import CustomFieldModelFilterForm -from utilities.forms import add_blank_choice, BootstrapMixin, StaticSelect, TagFilterField +from utilities.forms import ( + add_blank_choice, BootstrapMixin, DynamicModelMultipleChoiceField, StaticSelect, TagFilterField, +) from wireless.models import * __all__ = ( 'WirelessLANFilterForm', + 'WirelessLANGroupFilterForm', 'WirelessLinkFilterForm', ) +class WirelessLANGroupFilterForm(BootstrapMixin, CustomFieldModelFilterForm): + model = WirelessLANGroup + q = forms.CharField( + required=False, + widget=forms.TextInput(attrs={'placeholder': _('All Fields')}), + label=_('Search') + ) + parent_id = DynamicModelMultipleChoiceField( + queryset=WirelessLANGroup.objects.all(), + required=False, + label=_('Parent group'), + fetch_trigger='open' + ) + + class WirelessLANFilterForm(BootstrapMixin, CustomFieldModelFilterForm): model = WirelessLAN field_groups = [ - ['q', 'tag'], + ('q', 'tag'), + ('group_id',), ] q = forms.CharField( required=False, @@ -26,6 +45,13 @@ class WirelessLANFilterForm(BootstrapMixin, CustomFieldModelFilterForm): required=False, label='SSID' ) + group_id = DynamicModelMultipleChoiceField( + queryset=WirelessLANGroup.objects.all(), + required=False, + null_option='None', + label=_('Group'), + fetch_trigger='open' + ) tag = TagFilterField(model) diff --git a/netbox/wireless/forms/models.py b/netbox/wireless/forms/models.py index 174eb5983..ca20b6ea8 100644 --- a/netbox/wireless/forms/models.py +++ b/netbox/wireless/forms/models.py @@ -2,16 +2,37 @@ from dcim.models import Interface from extras.forms import CustomFieldModelForm from extras.models import Tag from ipam.models import VLAN -from utilities.forms import BootstrapMixin, DynamicModelChoiceField, DynamicModelMultipleChoiceField, StaticSelect +from utilities.forms import ( + BootstrapMixin, DynamicModelChoiceField, DynamicModelMultipleChoiceField, SlugField, StaticSelect, +) from wireless.models import * __all__ = ( 'WirelessLANForm', + 'WirelessLANGroupForm', 'WirelessLinkForm', ) +class WirelessLANGroupForm(BootstrapMixin, CustomFieldModelForm): + parent = DynamicModelChoiceField( + queryset=WirelessLANGroup.objects.all(), + required=False + ) + slug = SlugField() + + class Meta: + model = WirelessLANGroup + fields = [ + 'parent', 'name', 'slug', 'description', + ] + + class WirelessLANForm(BootstrapMixin, CustomFieldModelForm): + group = DynamicModelChoiceField( + queryset=WirelessLANGroup.objects.all(), + required=False + ) vlan = DynamicModelChoiceField( queryset=VLAN.objects.all(), required=False @@ -24,10 +45,10 @@ class WirelessLANForm(BootstrapMixin, CustomFieldModelForm): class Meta: model = WirelessLAN fields = [ - 'ssid', 'description', 'vlan', 'tags', + 'ssid', 'group', 'description', 'vlan', 'tags', ] fieldsets = ( - ('Wireless LAN', ('ssid', 'description', 'tags')), + ('Wireless LAN', ('ssid', 'group', 'description', 'tags')), ('VLAN', ('vlan',)), ) diff --git a/netbox/wireless/graphql/schema.py b/netbox/wireless/graphql/schema.py index 8297f4545..05fc57c4d 100644 --- a/netbox/wireless/graphql/schema.py +++ b/netbox/wireless/graphql/schema.py @@ -7,3 +7,9 @@ from .types import * class WirelessQuery(graphene.ObjectType): wirelesslan = ObjectField(WirelessLANType) wirelesslan_list = ObjectListField(WirelessLANType) + + wirelesslangroup = ObjectField(WirelessLANGroupType) + wirelesslangroup_list = ObjectListField(WirelessLANGroupType) + + wirelesslink = ObjectField(WirelessLinkType) + wirelesslink_list = ObjectListField(WirelessLinkType) diff --git a/netbox/wireless/graphql/types.py b/netbox/wireless/graphql/types.py index 0afd8e69a..4697cc44b 100644 --- a/netbox/wireless/graphql/types.py +++ b/netbox/wireless/graphql/types.py @@ -3,10 +3,19 @@ from netbox.graphql.types import ObjectType __all__ = ( 'WirelessLANType', + 'WirelessLANGroupType', 'WirelessLinkType', ) +class WirelessLANGroupType(ObjectType): + + class Meta: + model = models.WirelessLANGroup + fields = '__all__' + filterset_class = filtersets.WirelessLANGroupFilterSet + + class WirelessLANType(ObjectType): class Meta: diff --git a/netbox/wireless/migrations/0001_wireless.py b/netbox/wireless/migrations/0001_wireless.py index 8eb042d7d..068f4d64a 100644 --- a/netbox/wireless/migrations/0001_wireless.py +++ b/netbox/wireless/migrations/0001_wireless.py @@ -1,8 +1,7 @@ -# Generated by Django 3.2.8 on 2021-10-13 13:44 - import django.core.serializers.json from django.db import migrations, models import django.db.models.deletion +import mptt.fields import taggit.managers @@ -17,6 +16,27 @@ class Migration(migrations.Migration): ] operations = [ + migrations.CreateModel( + name='WirelessLANGroup', + fields=[ + ('created', models.DateField(auto_now_add=True, null=True)), + ('last_updated', models.DateTimeField(auto_now=True, null=True)), + ('custom_field_data', models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder)), + ('id', models.BigAutoField(primary_key=True, serialize=False)), + ('name', models.CharField(max_length=100, unique=True)), + ('slug', models.SlugField(max_length=100, unique=True)), + ('description', models.CharField(blank=True, max_length=200)), + ('lft', models.PositiveIntegerField(editable=False)), + ('rght', models.PositiveIntegerField(editable=False)), + ('tree_id', models.PositiveIntegerField(db_index=True, editable=False)), + ('level', models.PositiveIntegerField(editable=False)), + ('parent', mptt.fields.TreeForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='children', to='wireless.wirelesslangroup')), + ], + options={ + 'ordering': ('name', 'pk'), + 'unique_together': {('parent', 'name')}, + }, + ), migrations.CreateModel( name='WirelessLAN', fields=[ @@ -25,6 +45,7 @@ class Migration(migrations.Migration): ('custom_field_data', models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder)), ('id', models.BigAutoField(primary_key=True, serialize=False)), ('ssid', models.CharField(max_length=32)), + ('group', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='wireless_lans', to='wireless.wirelesslangroup')), ('description', models.CharField(blank=True, max_length=200)), ('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')), ('vlan', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='ipam.vlan')), diff --git a/netbox/wireless/models.py b/netbox/wireless/models.py index d02358f1c..12c4e55aa 100644 --- a/netbox/wireless/models.py +++ b/netbox/wireless/models.py @@ -1,20 +1,58 @@ from django.core.exceptions import ValidationError from django.db import models from django.urls import reverse +from mptt.models import MPTTModel, TreeForeignKey from dcim.choices import LinkStatusChoices from dcim.constants import WIRELESS_IFACE_TYPES from extras.utils import extras_features -from netbox.models import BigIDModel, PrimaryModel +from netbox.models import BigIDModel, NestedGroupModel, PrimaryModel from utilities.querysets import RestrictedQuerySet from .constants import SSID_MAX_LENGTH __all__ = ( 'WirelessLAN', + 'WirelessLANGroup', 'WirelessLink', ) +@extras_features('custom_fields', 'custom_links', 'export_templates', 'webhooks') +class WirelessLANGroup(NestedGroupModel): + """ + A nested grouping of WirelessLANs + """ + name = models.CharField( + max_length=100, + unique=True + ) + slug = models.SlugField( + max_length=100, + unique=True + ) + parent = TreeForeignKey( + to='self', + on_delete=models.CASCADE, + related_name='children', + blank=True, + null=True, + db_index=True + ) + description = models.CharField( + max_length=200, + blank=True + ) + + class Meta: + ordering = ('name', 'pk') + unique_together = ( + ('parent', 'name') + ) + + def get_absolute_url(self): + return reverse('wireless:wirelesslangroup', args=[self.pk]) + + @extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks') class WirelessLAN(PrimaryModel): """ @@ -24,6 +62,13 @@ class WirelessLAN(PrimaryModel): max_length=SSID_MAX_LENGTH, verbose_name='SSID' ) + group = models.ForeignKey( + to='wireless.WirelessLANGroup', + on_delete=models.SET_NULL, + related_name='wireless_lans', + blank=True, + null=True + ) vlan = models.ForeignKey( to='ipam.VLAN', on_delete=models.PROTECT, @@ -100,7 +145,7 @@ class WirelessLink(PrimaryModel): objects = RestrictedQuerySet.as_manager() - clone_fields = ('ssid', 'status') + clone_fields = ('ssid', 'group', 'status') class Meta: ordering = ['pk'] diff --git a/netbox/wireless/tables.py b/netbox/wireless/tables.py index 9b0ef7291..58d77b56f 100644 --- a/netbox/wireless/tables.py +++ b/netbox/wireless/tables.py @@ -1,14 +1,35 @@ import django_tables2 as tables +from utilities.tables import ( + BaseTable, ButtonsColumn, ChoiceFieldColumn, LinkedCountColumn, MPTTColumn, TagColumn, ToggleColumn, +) from .models import * -from utilities.tables import BaseTable, ChoiceFieldColumn, TagColumn, ToggleColumn __all__ = ( 'WirelessLANTable', + 'WirelessLANGroupTable', 'WirelessLinkTable', ) +class WirelessLANGroupTable(BaseTable): + pk = ToggleColumn() + name = MPTTColumn( + linkify=True + ) + wirelesslan_count = LinkedCountColumn( + viewname='wireless:wirelesslan_list', + url_params={'group_id': 'pk'}, + verbose_name='Wireless LANs' + ) + actions = ButtonsColumn(WirelessLANGroup) + + class Meta(BaseTable.Meta): + model = WirelessLANGroup + fields = ('pk', 'name', 'wirelesslan_count', 'description', 'slug', 'actions') + default_columns = ('pk', 'name', 'wirelesslan_count', 'description', 'actions') + + class WirelessLANTable(BaseTable): pk = ToggleColumn() ssid = tables.Column( diff --git a/netbox/wireless/urls.py b/netbox/wireless/urls.py index 21d704e6a..684f55ad5 100644 --- a/netbox/wireless/urls.py +++ b/netbox/wireless/urls.py @@ -7,6 +7,17 @@ from .models import * app_name = 'wireless' urlpatterns = ( + # Wireless LAN groups + path('wireless-lan-groups/', views.WirelessLANGroupListView.as_view(), name='wirelesslangroup_list'), + path('wireless-lan-groups/add/', views.WirelessLANGroupEditView.as_view(), name='wirelesslangroup_add'), + path('wireless-lan-groups/import/', views.WirelessLANGroupBulkImportView.as_view(), name='wirelesslangroup_import'), + path('wireless-lan-groups/edit/', views.WirelessLANGroupBulkEditView.as_view(), name='wirelesslangroup_bulk_edit'), + path('wireless-lan-groups/delete/', views.WirelessLANGroupBulkDeleteView.as_view(), name='wirelesslangroup_bulk_delete'), + path('wireless-lan-groups//', views.WirelessLANGroupView.as_view(), name='wirelesslangroup'), + path('wireless-lan-groups//edit/', views.WirelessLANGroupEditView.as_view(), name='wirelesslangroup_edit'), + path('wireless-lan-groups//delete/', views.WirelessLANGroupDeleteView.as_view(), name='wirelesslangroup_delete'), + path('wireless-lan-groups//changelog/', ObjectChangeLogView.as_view(), name='wirelesslangroup_changelog', kwargs={'model': WirelessLANGroup}), + # Wireless LANs path('wireless-lans/', views.WirelessLANListView.as_view(), name='wirelesslan_list'), path('wireless-lans/add/', views.WirelessLANEditView.as_view(), name='wirelesslan_add'), diff --git a/netbox/wireless/views.py b/netbox/wireless/views.py index 041ffbd42..6405d46df 100644 --- a/netbox/wireless/views.py +++ b/netbox/wireless/views.py @@ -1,8 +1,81 @@ from netbox.views import generic +from utilities.tables import paginate_table from . import filtersets, forms, tables from .models import * +# +# Wireless LAN groups +# + +class WirelessLANGroupListView(generic.ObjectListView): + queryset = WirelessLANGroup.objects.add_related_count( + WirelessLANGroup.objects.all(), + WirelessLAN, + 'group', + 'wirelesslan_count', + cumulative=True + ) + filterset = filtersets.WirelessLANGroupFilterSet + filterset_form = forms.WirelessLANGroupFilterForm + table = tables.WirelessLANGroupTable + + +class WirelessLANGroupView(generic.ObjectView): + queryset = WirelessLANGroup.objects.all() + + def get_extra_context(self, request, instance): + wirelesslans = WirelessLAN.objects.restrict(request.user, 'view').filter( + group=instance + ) + wirelesslans_table = tables.WirelessLANTable(wirelesslans, exclude=('group',)) + paginate_table(wirelesslans_table, request) + + return { + 'wirelesslans_table': wirelesslans_table, + } + + +class WirelessLANGroupEditView(generic.ObjectEditView): + queryset = WirelessLANGroup.objects.all() + model_form = forms.WirelessLANGroupForm + + +class WirelessLANGroupDeleteView(generic.ObjectDeleteView): + queryset = WirelessLANGroup.objects.all() + + +class WirelessLANGroupBulkImportView(generic.BulkImportView): + queryset = WirelessLANGroup.objects.all() + model_form = forms.WirelessLANGroupCSVForm + table = tables.WirelessLANGroupTable + + +class WirelessLANGroupBulkEditView(generic.BulkEditView): + queryset = WirelessLANGroup.objects.add_related_count( + WirelessLANGroup.objects.all(), + WirelessLAN, + 'group', + 'wirelesslan_count', + cumulative=True + ) + filterset = filtersets.WirelessLANGroupFilterSet + table = tables.WirelessLANGroupTable + form = forms.WirelessLANGroupBulkEditForm + + +class WirelessLANGroupBulkDeleteView(generic.BulkDeleteView): + queryset = WirelessLANGroup.objects.add_related_count( + WirelessLANGroup.objects.all(), + WirelessLAN, + 'group', + 'wirelesslan_count', + cumulative=True + ) + filterset = filtersets.WirelessLANGroupFilterSet + table = tables.WirelessLANGroupTable + + # # Wireless LANs #