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:
@ -308,6 +308,7 @@ class APIRootView(APIView):
|
|||||||
('tenancy', reverse('tenancy-api:api-root', request=request, format=format)),
|
('tenancy', reverse('tenancy-api:api-root', request=request, format=format)),
|
||||||
('users', reverse('users-api:api-root', request=request, format=format)),
|
('users', reverse('users-api:api-root', request=request, format=format)),
|
||||||
('virtualization', reverse('virtualization-api:api-root', request=request, format=format)),
|
('virtualization', reverse('virtualization-api:api-root', request=request, format=format)),
|
||||||
|
('wireless', reverse('wireless-api:api-root', request=request, format=format)),
|
||||||
)))
|
)))
|
||||||
|
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ from ipam.graphql.schema import IPAMQuery
|
|||||||
from tenancy.graphql.schema import TenancyQuery
|
from tenancy.graphql.schema import TenancyQuery
|
||||||
from users.graphql.schema import UsersQuery
|
from users.graphql.schema import UsersQuery
|
||||||
from virtualization.graphql.schema import VirtualizationQuery
|
from virtualization.graphql.schema import VirtualizationQuery
|
||||||
|
from wireless.graphql.schema import WirelessQuery
|
||||||
|
|
||||||
|
|
||||||
class Query(
|
class Query(
|
||||||
@ -17,6 +18,7 @@ class Query(
|
|||||||
TenancyQuery,
|
TenancyQuery,
|
||||||
UsersQuery,
|
UsersQuery,
|
||||||
VirtualizationQuery,
|
VirtualizationQuery,
|
||||||
|
WirelessQuery,
|
||||||
graphene.ObjectType
|
graphene.ObjectType
|
||||||
):
|
):
|
||||||
pass
|
pass
|
||||||
|
@ -188,6 +188,19 @@ CONNECTIONS_MENU = Menu(
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
WIRELESS_MENU = Menu(
|
||||||
|
label='Wireless',
|
||||||
|
icon_class='mdi mdi-wifi',
|
||||||
|
groups=(
|
||||||
|
MenuGroup(
|
||||||
|
label='Wireless',
|
||||||
|
items=(
|
||||||
|
get_model_item('wireless', 'ssid', 'SSIDs'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
IPAM_MENU = Menu(
|
IPAM_MENU = Menu(
|
||||||
label='IPAM',
|
label='IPAM',
|
||||||
icon_class='mdi mdi-counter',
|
icon_class='mdi mdi-counter',
|
||||||
@ -343,6 +356,7 @@ MENUS = [
|
|||||||
ORGANIZATION_MENU,
|
ORGANIZATION_MENU,
|
||||||
DEVICES_MENU,
|
DEVICES_MENU,
|
||||||
CONNECTIONS_MENU,
|
CONNECTIONS_MENU,
|
||||||
|
WIRELESS_MENU,
|
||||||
IPAM_MENU,
|
IPAM_MENU,
|
||||||
VIRTUALIZATION_MENU,
|
VIRTUALIZATION_MENU,
|
||||||
CIRCUITS_MENU,
|
CIRCUITS_MENU,
|
||||||
|
@ -326,6 +326,7 @@ INSTALLED_APPS = [
|
|||||||
'users',
|
'users',
|
||||||
'utilities',
|
'utilities',
|
||||||
'virtualization',
|
'virtualization',
|
||||||
|
'wireless',
|
||||||
'django_rq', # Must come after extras to allow overriding management commands
|
'django_rq', # Must come after extras to allow overriding management commands
|
||||||
'drf_yasg',
|
'drf_yasg',
|
||||||
]
|
]
|
||||||
|
@ -48,6 +48,7 @@ _patterns = [
|
|||||||
path('tenancy/', include('tenancy.urls')),
|
path('tenancy/', include('tenancy.urls')),
|
||||||
path('user/', include('users.urls')),
|
path('user/', include('users.urls')),
|
||||||
path('virtualization/', include('virtualization.urls')),
|
path('virtualization/', include('virtualization.urls')),
|
||||||
|
path('wireless/', include('wireless.urls')),
|
||||||
|
|
||||||
# API
|
# API
|
||||||
path('api/', APIRootView.as_view(), name='api-root'),
|
path('api/', APIRootView.as_view(), name='api-root'),
|
||||||
@ -58,6 +59,7 @@ _patterns = [
|
|||||||
path('api/tenancy/', include('tenancy.api.urls')),
|
path('api/tenancy/', include('tenancy.api.urls')),
|
||||||
path('api/users/', include('users.api.urls')),
|
path('api/users/', include('users.api.urls')),
|
||||||
path('api/virtualization/', include('virtualization.api.urls')),
|
path('api/virtualization/', include('virtualization.api.urls')),
|
||||||
|
path('api/wireless/', include('wireless.api.urls')),
|
||||||
path('api/status/', StatusView.as_view(), name='api-status'),
|
path('api/status/', StatusView.as_view(), name='api-status'),
|
||||||
path('api/docs/', schema_view.with_ui('swagger', cache_timeout=86400), name='api_docs'),
|
path('api/docs/', schema_view.with_ui('swagger', cache_timeout=86400), name='api_docs'),
|
||||||
path('api/redoc/', schema_view.with_ui('redoc', cache_timeout=86400), name='api_redocs'),
|
path('api/redoc/', schema_view.with_ui('redoc', cache_timeout=86400), name='api_redocs'),
|
||||||
|
46
netbox/templates/wireless/ssid.html
Normal file
46
netbox/templates/wireless/ssid.html
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
{% extends 'generic/object.html' %}
|
||||||
|
{% load helpers %}
|
||||||
|
{% load plugins %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col col-md-6">
|
||||||
|
<div class="card">
|
||||||
|
<h5 class="card-header">SSID</h5>
|
||||||
|
<div class="card-body">
|
||||||
|
<table class="table table-hover attr-table">
|
||||||
|
<tr>
|
||||||
|
<th scope="row">Name</th>
|
||||||
|
<td>{{ object.name }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">Description</th>
|
||||||
|
<td>{{ object.description|placeholder }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">VLAN</th>
|
||||||
|
<td>
|
||||||
|
{% if object.vlan %}
|
||||||
|
<a href="{{ object.vlan.get_absolute_url }}">{{ object.vlan }}</a>
|
||||||
|
{% else %}
|
||||||
|
<span class="text-muted">None</span>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% include 'extras/inc/tags_panel.html' with tags=object.tags.all url='dcim:site_list' %}
|
||||||
|
{% plugin_left_page object %}
|
||||||
|
</div>
|
||||||
|
<div class="col col-md-6">
|
||||||
|
{% include 'inc/custom_fields_panel.html' %}
|
||||||
|
{% plugin_right_page object %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col col-md-12">
|
||||||
|
{% plugin_full_width_page object %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
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