mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
Introduce the wireless app and SSID model
This commit is contained in:
0
netbox/wireless/__init__.py
Normal file
0
netbox/wireless/__init__.py
Normal file
0
netbox/wireless/api/__init__.py
Normal file
0
netbox/wireless/api/__init__.py
Normal file
16
netbox/wireless/api/nested_serializers.py
Normal file
16
netbox/wireless/api/nested_serializers.py
Normal file
@@ -0,0 +1,16 @@
|
||||
from rest_framework import serializers
|
||||
|
||||
from netbox.api import WritableNestedSerializer
|
||||
from wireless.models import *
|
||||
|
||||
__all__ = (
|
||||
'NestedSSIDSerializer',
|
||||
)
|
||||
|
||||
|
||||
class NestedSSIDSerializer(WritableNestedSerializer):
|
||||
url = serializers.HyperlinkedIdentityField(view_name='wireless-api:ssid-detail')
|
||||
|
||||
class Meta:
|
||||
model = SSID
|
||||
fields = ['id', 'url', 'display', 'name']
|
21
netbox/wireless/api/serializers.py
Normal file
21
netbox/wireless/api/serializers.py
Normal file
@@ -0,0 +1,21 @@
|
||||
from rest_framework import serializers
|
||||
|
||||
from dcim.api.serializers import NestedInterfaceSerializer
|
||||
from ipam.api.serializers import NestedVLANSerializer
|
||||
from netbox.api.serializers import PrimaryModelSerializer
|
||||
from wireless.models import *
|
||||
|
||||
__all__ = (
|
||||
'SSIDSerializer',
|
||||
)
|
||||
|
||||
|
||||
class SSIDSerializer(PrimaryModelSerializer):
|
||||
url = serializers.HyperlinkedIdentityField(view_name='wireless-api:ssid-detail')
|
||||
vlan = NestedVLANSerializer(required=False, allow_null=True)
|
||||
|
||||
class Meta:
|
||||
model = SSID
|
||||
fields = [
|
||||
'id', 'url', 'display', 'name', 'description', 'vlan',
|
||||
]
|
12
netbox/wireless/api/urls.py
Normal file
12
netbox/wireless/api/urls.py
Normal file
@@ -0,0 +1,12 @@
|
||||
from netbox.api import OrderedDefaultRouter
|
||||
from . import views
|
||||
|
||||
|
||||
router = OrderedDefaultRouter()
|
||||
router.APIRootView = views.WirelessRootView
|
||||
|
||||
# SSIDs
|
||||
router.register('ssids', views.SSIDViewSet)
|
||||
|
||||
app_name = 'wireless-api'
|
||||
urlpatterns = router.urls
|
24
netbox/wireless/api/views.py
Normal file
24
netbox/wireless/api/views.py
Normal file
@@ -0,0 +1,24 @@
|
||||
from rest_framework.routers import APIRootView
|
||||
|
||||
from extras.api.views import CustomFieldModelViewSet
|
||||
from wireless import filtersets
|
||||
from wireless.models import *
|
||||
from . import serializers
|
||||
|
||||
|
||||
class WirelessRootView(APIRootView):
|
||||
"""
|
||||
Wireless API root view
|
||||
"""
|
||||
def get_view_name(self):
|
||||
return 'Wireless'
|
||||
|
||||
|
||||
#
|
||||
# Providers
|
||||
#
|
||||
|
||||
class SSIDViewSet(CustomFieldModelViewSet):
|
||||
queryset = SSID.objects.prefetch_related('tags')
|
||||
serializer_class = serializers.SSIDSerializer
|
||||
filterset_class = filtersets.SSIDFilterSet
|
5
netbox/wireless/apps.py
Normal file
5
netbox/wireless/apps.py
Normal file
@@ -0,0 +1,5 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class WirelessConfig(AppConfig):
|
||||
name = 'wireless'
|
31
netbox/wireless/filtersets.py
Normal file
31
netbox/wireless/filtersets.py
Normal file
@@ -0,0 +1,31 @@
|
||||
import django_filters
|
||||
from django.db.models import Q
|
||||
|
||||
from extras.filters import TagFilter
|
||||
from netbox.filtersets import PrimaryModelFilterSet
|
||||
from .models import *
|
||||
|
||||
__all__ = (
|
||||
'SSIDFilterSet',
|
||||
)
|
||||
|
||||
|
||||
class SSIDFilterSet(PrimaryModelFilterSet):
|
||||
q = django_filters.CharFilter(
|
||||
method='search',
|
||||
label='Search',
|
||||
)
|
||||
tag = TagFilter()
|
||||
|
||||
class Meta:
|
||||
model = SSID
|
||||
fields = ['id', 'name']
|
||||
|
||||
def search(self, queryset, name, value):
|
||||
if not value.strip():
|
||||
return queryset
|
||||
qs_filter = (
|
||||
Q(name__icontains=value) |
|
||||
Q(description__icontains=value)
|
||||
)
|
||||
return queryset.filter(qs_filter)
|
4
netbox/wireless/forms/__init__.py
Normal file
4
netbox/wireless/forms/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
||||
from .models import *
|
||||
from .filtersets import *
|
||||
from .bulk_edit import *
|
||||
from .bulk_import import *
|
29
netbox/wireless/forms/bulk_edit.py
Normal file
29
netbox/wireless/forms/bulk_edit.py
Normal file
@@ -0,0 +1,29 @@
|
||||
from django import forms
|
||||
|
||||
from dcim.models import *
|
||||
from extras.forms import AddRemoveTagsForm, CustomFieldModelBulkEditForm
|
||||
from ipam.models import VLAN
|
||||
from utilities.forms import BootstrapMixin, DynamicModelChoiceField
|
||||
|
||||
__all__ = (
|
||||
'SSIDBulkEditForm',
|
||||
)
|
||||
|
||||
|
||||
class SSIDBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldModelBulkEditForm):
|
||||
pk = forms.ModelMultipleChoiceField(
|
||||
queryset=PowerFeed.objects.all(),
|
||||
widget=forms.MultipleHiddenInput
|
||||
)
|
||||
vlan = DynamicModelChoiceField(
|
||||
queryset=VLAN.objects.all(),
|
||||
required=False,
|
||||
)
|
||||
description = forms.CharField(
|
||||
required=False
|
||||
)
|
||||
|
||||
class Meta:
|
||||
nullable_fields = [
|
||||
'vlan', 'description',
|
||||
]
|
20
netbox/wireless/forms/bulk_import.py
Normal file
20
netbox/wireless/forms/bulk_import.py
Normal file
@@ -0,0 +1,20 @@
|
||||
from extras.forms import CustomFieldModelCSVForm
|
||||
from ipam.models import VLAN
|
||||
from utilities.forms import CSVModelChoiceField
|
||||
from wireless.models import SSID
|
||||
|
||||
__all__ = (
|
||||
'SSIDCSVForm',
|
||||
)
|
||||
|
||||
|
||||
class SSIDCSVForm(CustomFieldModelCSVForm):
|
||||
vlan = CSVModelChoiceField(
|
||||
queryset=VLAN.objects.all(),
|
||||
to_field_name='name',
|
||||
help_text='Bridged VLAN'
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = SSID
|
||||
fields = ('name', 'description', 'vlan')
|
19
netbox/wireless/forms/filtersets.py
Normal file
19
netbox/wireless/forms/filtersets.py
Normal file
@@ -0,0 +1,19 @@
|
||||
from django import forms
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from dcim.models import *
|
||||
from extras.forms import CustomFieldModelFilterForm
|
||||
from utilities.forms import BootstrapMixin, TagFilterField
|
||||
|
||||
|
||||
class SSIDFilterForm(BootstrapMixin, CustomFieldModelFilterForm):
|
||||
model = PowerFeed
|
||||
field_groups = [
|
||||
['q', 'tag'],
|
||||
]
|
||||
q = forms.CharField(
|
||||
required=False,
|
||||
widget=forms.TextInput(attrs={'placeholder': _('All Fields')}),
|
||||
label=_('Search')
|
||||
)
|
||||
tag = TagFilterField(model)
|
32
netbox/wireless/forms/models.py
Normal file
32
netbox/wireless/forms/models.py
Normal file
@@ -0,0 +1,32 @@
|
||||
from dcim.constants import *
|
||||
from dcim.models import *
|
||||
from extras.forms import CustomFieldModelForm
|
||||
from extras.models import Tag
|
||||
from ipam.models import VLAN
|
||||
from utilities.forms import BootstrapMixin, DynamicModelChoiceField, DynamicModelMultipleChoiceField
|
||||
from wireless.models import SSID
|
||||
|
||||
__all__ = (
|
||||
'SSIDForm',
|
||||
)
|
||||
|
||||
|
||||
class SSIDForm(BootstrapMixin, CustomFieldModelForm):
|
||||
vlan = DynamicModelChoiceField(
|
||||
queryset=VLAN.objects.all(),
|
||||
required=False
|
||||
)
|
||||
tags = DynamicModelMultipleChoiceField(
|
||||
queryset=Tag.objects.all(),
|
||||
required=False
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = SSID
|
||||
fields = [
|
||||
'name', 'description', 'vlan', 'tags',
|
||||
]
|
||||
fieldsets = (
|
||||
('SSID', ('name', 'description', 'tags')),
|
||||
('VLAN', ('vlan',)),
|
||||
)
|
0
netbox/wireless/graphql/__init__.py
Normal file
0
netbox/wireless/graphql/__init__.py
Normal file
9
netbox/wireless/graphql/schema.py
Normal file
9
netbox/wireless/graphql/schema.py
Normal file
@@ -0,0 +1,9 @@
|
||||
import graphene
|
||||
|
||||
from netbox.graphql.fields import ObjectField, ObjectListField
|
||||
from .types import *
|
||||
|
||||
|
||||
class WirelessQuery(graphene.ObjectType):
|
||||
ssid = ObjectField(SSIDType)
|
||||
ssid_list = ObjectListField(SSIDType)
|
14
netbox/wireless/graphql/types.py
Normal file
14
netbox/wireless/graphql/types.py
Normal file
@@ -0,0 +1,14 @@
|
||||
from wireless import filtersets, models
|
||||
from netbox.graphql.types import ObjectType
|
||||
|
||||
__all__ = (
|
||||
'SSIDType',
|
||||
)
|
||||
|
||||
|
||||
class SSIDType(ObjectType):
|
||||
|
||||
class Meta:
|
||||
model = models.SSID
|
||||
fields = '__all__'
|
||||
filterset_class = filtersets.SSIDFilterSet
|
36
netbox/wireless/migrations/0001_initial.py
Normal file
36
netbox/wireless/migrations/0001_initial.py
Normal file
@@ -0,0 +1,36 @@
|
||||
import django.core.serializers.json
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import taggit.managers
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
('dcim', '0136_wireless'),
|
||||
('extras', '0062_clear_secrets_changelog'),
|
||||
('ipam', '0050_iprange'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='SSID',
|
||||
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=32)),
|
||||
('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')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'SSID',
|
||||
'verbose_name_plural': 'SSIDs',
|
||||
'ordering': ('name', 'pk'),
|
||||
},
|
||||
),
|
||||
]
|
0
netbox/wireless/migrations/__init__.py
Normal file
0
netbox/wireless/migrations/__init__.py
Normal file
40
netbox/wireless/models.py
Normal file
40
netbox/wireless/models.py
Normal file
@@ -0,0 +1,40 @@
|
||||
from django.db import models
|
||||
|
||||
from extras.utils import extras_features
|
||||
from netbox.models import PrimaryModel
|
||||
from utilities.querysets import RestrictedQuerySet
|
||||
|
||||
__all__ = (
|
||||
'SSID',
|
||||
)
|
||||
|
||||
|
||||
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
|
||||
class SSID(PrimaryModel):
|
||||
"""
|
||||
A service set identifier belonging to a wireless network.
|
||||
"""
|
||||
name = models.CharField(
|
||||
max_length=32
|
||||
)
|
||||
vlan = models.ForeignKey(
|
||||
to='ipam.VLAN',
|
||||
on_delete=models.PROTECT,
|
||||
blank=True,
|
||||
null=True,
|
||||
verbose_name='VLAN'
|
||||
)
|
||||
description = models.CharField(
|
||||
max_length=200,
|
||||
blank=True
|
||||
)
|
||||
|
||||
objects = RestrictedQuerySet.as_manager()
|
||||
|
||||
class Meta:
|
||||
ordering = ('name', 'pk')
|
||||
verbose_name = 'SSID'
|
||||
verbose_name_plural = 'SSIDs'
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
24
netbox/wireless/tables.py
Normal file
24
netbox/wireless/tables.py
Normal file
@@ -0,0 +1,24 @@
|
||||
import django_tables2 as tables
|
||||
|
||||
from .models import SSID
|
||||
from utilities.tables import BaseTable, TagColumn, ToggleColumn
|
||||
|
||||
__all__ = (
|
||||
'SSIDTable',
|
||||
)
|
||||
|
||||
|
||||
class SSIDTable(BaseTable):
|
||||
pk = ToggleColumn()
|
||||
id = tables.Column(
|
||||
linkify=True,
|
||||
verbose_name='ID'
|
||||
)
|
||||
tags = TagColumn(
|
||||
url_name='dcim:cable_list'
|
||||
)
|
||||
|
||||
class Meta(BaseTable.Meta):
|
||||
model = SSID
|
||||
fields = ('pk', 'id', 'name', 'description', 'vlan')
|
||||
default_columns = ('pk', 'name', 'description', 'vlan')
|
22
netbox/wireless/urls.py
Normal file
22
netbox/wireless/urls.py
Normal file
@@ -0,0 +1,22 @@
|
||||
from django.urls import path
|
||||
|
||||
from extras.views import ObjectChangeLogView, ObjectJournalView
|
||||
from . import views
|
||||
from .models import *
|
||||
|
||||
app_name = 'wireless'
|
||||
urlpatterns = (
|
||||
|
||||
# SSIDs
|
||||
path('ssids/', views.SSIDListView.as_view(), name='ssid_list'),
|
||||
path('ssids/add/', views.SSIDEditView.as_view(), name='ssid_add'),
|
||||
path('ssids/import/', views.SSIDBulkImportView.as_view(), name='ssid_import'),
|
||||
path('ssids/edit/', views.SSIDBulkEditView.as_view(), name='ssid_bulk_edit'),
|
||||
path('ssids/delete/', views.SSIDBulkDeleteView.as_view(), name='ssid_bulk_delete'),
|
||||
path('ssids/<int:pk>/', views.SSIDView.as_view(), name='ssid'),
|
||||
path('ssids/<int:pk>/edit/', views.SSIDEditView.as_view(), name='ssid_edit'),
|
||||
path('ssids/<int:pk>/delete/', views.SSIDDeleteView.as_view(), name='ssid_delete'),
|
||||
path('ssids/<int:pk>/changelog/', ObjectChangeLogView.as_view(), name='ssid_changelog', kwargs={'model': SSID}),
|
||||
path('ssids/<int:pk>/journal/', ObjectJournalView.as_view(), name='ssid_journal', kwargs={'model': SSID}),
|
||||
|
||||
)
|
46
netbox/wireless/views.py
Normal file
46
netbox/wireless/views.py
Normal file
@@ -0,0 +1,46 @@
|
||||
from netbox.views import generic
|
||||
from . import filtersets, forms, tables
|
||||
from .models import *
|
||||
|
||||
|
||||
#
|
||||
# SSIDs
|
||||
#
|
||||
|
||||
class SSIDListView(generic.ObjectListView):
|
||||
queryset = SSID.objects.all()
|
||||
filterset = filtersets.SSIDFilterSet
|
||||
filterset_form = forms.SSIDFilterForm
|
||||
table = tables.SSIDTable
|
||||
|
||||
|
||||
class SSIDView(generic.ObjectView):
|
||||
queryset = SSID.objects.prefetch_related('power_panel', 'rack')
|
||||
|
||||
|
||||
class SSIDEditView(generic.ObjectEditView):
|
||||
queryset = SSID.objects.all()
|
||||
model_form = forms.SSIDForm
|
||||
|
||||
|
||||
class SSIDDeleteView(generic.ObjectDeleteView):
|
||||
queryset = SSID.objects.all()
|
||||
|
||||
|
||||
class SSIDBulkImportView(generic.BulkImportView):
|
||||
queryset = SSID.objects.all()
|
||||
model_form = forms.SSIDCSVForm
|
||||
table = tables.SSIDTable
|
||||
|
||||
|
||||
class SSIDBulkEditView(generic.BulkEditView):
|
||||
queryset = SSID.objects.prefetch_related('power_panel', 'rack')
|
||||
filterset = filtersets.SSIDFilterSet
|
||||
table = tables.SSIDTable
|
||||
form = forms.SSIDBulkEditForm
|
||||
|
||||
|
||||
class SSIDBulkDeleteView(generic.BulkDeleteView):
|
||||
queryset = SSID.objects.prefetch_related('power_panel', 'rack')
|
||||
filterset = filtersets.SSIDFilterSet
|
||||
table = tables.SSIDTable
|
Reference in New Issue
Block a user