Add WirelessLANGroup model

This commit is contained in:
jeremystretch 2021-10-13 16:40:12 -04:00
parent 43f2d4a331
commit 01f791a44e
19 changed files with 429 additions and 16 deletions

View File

@ -168,6 +168,7 @@ CONNECTIONS_MENU = Menu(
label='Connections', label='Connections',
items=( items=(
get_model_item('dcim', 'cable', 'Cables', actions=['import']), get_model_item('dcim', 'cable', 'Cables', actions=['import']),
get_model_item('wireless', 'wirelesslink', 'Wirelesss Links', actions=['import']),
MenuItem( MenuItem(
link='dcim:interface_connections_list', link='dcim:interface_connections_list',
link_text='Interface Connections', link_text='Interface Connections',
@ -196,7 +197,7 @@ WIRELESS_MENU = Menu(
label='Wireless', label='Wireless',
items=( items=(
get_model_item('wireless', 'wirelesslan', 'Wireless LANs'), get_model_item('wireless', 'wirelesslan', 'Wireless LANs'),
get_model_item('wireless', 'wirelesslink', 'Wirelesss Links', actions=['import']), get_model_item('wireless', 'wirelesslangroup', 'Wireless LAN Groups'),
), ),
), ),
), ),

View File

@ -13,6 +13,16 @@
<th scope="row">SSID</th> <th scope="row">SSID</th>
<td>{{ object.ssid }}</td> <td>{{ object.ssid }}</td>
</tr> </tr>
<tr>
<td>Group</td>
<td>
{% if object.group %}
<a href="{{ object.group.get_absolute_url }}">{{ object.group }}</a>
{% else %}
<span class="text-muted">None</span>
{% endif %}
</td>
</tr>
<tr> <tr>
<th scope="row">Description</th> <th scope="row">Description</th>
<td>{{ object.description|placeholder }}</td> <td>{{ object.description|placeholder }}</td>

View File

@ -0,0 +1,72 @@
{% extends 'generic/object.html' %}
{% load helpers %}
{% load plugins %}
{% block breadcrumbs %}
{{ block.super }}
{% for group in object.get_ancestors %}
<li class="breadcrumb-item"><a href="{% url 'wireless:wirelesslangroup_list' %}?parent_id={{ group.pk }}">{{ group }}</a></li>
{% endfor %}
{% endblock %}
{% block content %}
<div class="row mb-3">
<div class="col col-md-6">
<div class="card">
<h5 class="card-header">Wireless LAN Group</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">Parent</th>
<td>
{% if object.parent %}
<a href="{{ object.parent.get_absolute_url }}">{{ object.parent }}</a>
{% else %}
<span class="text-muted">&mdash;</span>
{% endif %}
</td>
</tr>
<tr>
<th scope="row">Wireless LANs</th>
<td>
<a href="{% url 'wireless:wirelesslan_list' %}?group_id={{ object.pk }}">{{ wirelesslans_table.rows|length }}</a>
</td>
</tr>
</table>
</div>
</div>
{% 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 mb-3">
<div class="col col-md-12">
<div class="card">
<div class="card-header">Wireless LANs</div>
<div class="card-body">
{% include 'inc/table.html' with table=wirelesslans_table %}
</div>
{% if perms.wireless.add_wirelesslan %}
<div class="card-footer text-end noprint">
<a href="{% url 'wireless:wirelesslan_add' %}?group={{ object.pk }}" class="btn btn-sm btn-primary">
<span class="mdi mdi-plus-thick" aria-hidden="true"></span> Add Wireless LAN
</a>
</div>
{% endif %}
</div>
{% include 'inc/paginator.html' with paginator=wirelesslans_table.paginator page=wirelesslans_table.page %}
{% plugin_full_width_page object %}
</div>
</div>
{% endblock %}

View File

@ -5,10 +5,21 @@ from wireless.models import *
__all__ = ( __all__ = (
'NestedWirelessLANSerializer', 'NestedWirelessLANSerializer',
'NestedWirelessLANGroupSerializer',
'NestedWirelessLinkSerializer', '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): class NestedWirelessLANSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='wireless-api:wirelesslan-detail') url = serializers.HyperlinkedIdentityField(view_name='wireless-api:wirelesslan-detail')

View File

@ -4,7 +4,7 @@ from dcim.choices import LinkStatusChoices
from dcim.api.serializers import NestedInterfaceSerializer from dcim.api.serializers import NestedInterfaceSerializer
from ipam.api.serializers import NestedVLANSerializer from ipam.api.serializers import NestedVLANSerializer
from netbox.api import ChoiceField from netbox.api import ChoiceField
from netbox.api.serializers import PrimaryModelSerializer from netbox.api.serializers import NestedGroupModelSerializer, PrimaryModelSerializer
from wireless.models import * from wireless.models import *
from .nested_serializers 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): class WirelessLANSerializer(PrimaryModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='wireless-api:wirelesslan-detail') url = serializers.HyperlinkedIdentityField(view_name='wireless-api:wirelesslan-detail')
vlan = NestedVLANSerializer(required=False, allow_null=True) vlan = NestedVLANSerializer(required=False, allow_null=True)

View File

@ -5,6 +5,7 @@ from . import views
router = OrderedDefaultRouter() router = OrderedDefaultRouter()
router.APIRootView = views.WirelessRootView router.APIRootView = views.WirelessRootView
router.register('wireless-lan-groupss', views.WirelessLANGroupViewSet)
router.register('wireless-lans', views.WirelessLANViewSet) router.register('wireless-lans', views.WirelessLANViewSet)
router.register('wireless-links', views.WirelessLinkViewSet) router.register('wireless-links', views.WirelessLinkViewSet)

View File

@ -14,6 +14,18 @@ class WirelessRootView(APIRootView):
return 'Wireless' 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): class WirelessLANViewSet(CustomFieldModelViewSet):
queryset = WirelessLAN.objects.prefetch_related('vlan', 'tags') queryset = WirelessLAN.objects.prefetch_related('vlan', 'tags')
serializer_class = serializers.WirelessLANSerializer serializer_class = serializers.WirelessLANSerializer

View File

@ -3,15 +3,31 @@ from django.db.models import Q
from dcim.choices import LinkStatusChoices from dcim.choices import LinkStatusChoices
from extras.filters import TagFilter from extras.filters import TagFilter
from netbox.filtersets import PrimaryModelFilterSet from netbox.filtersets import OrganizationalModelFilterSet, PrimaryModelFilterSet
from .models import * from .models import *
__all__ = ( __all__ = (
'WirelessLANFilterSet', 'WirelessLANFilterSet',
'WirelessLANGroupFilterSet',
'WirelessLinkFilterSet', '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): class WirelessLANFilterSet(PrimaryModelFilterSet):
q = django_filters.CharFilter( q = django_filters.CharFilter(
method='search', method='search',

View File

@ -9,15 +9,38 @@ from wireless.models import *
__all__ = ( __all__ = (
'WirelessLANBulkEditForm', 'WirelessLANBulkEditForm',
'WirelessLANGroupBulkEditForm',
'WirelessLinkBulkEditForm', '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): class WirelessLANBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldModelBulkEditForm):
pk = forms.ModelMultipleChoiceField( pk = forms.ModelMultipleChoiceField(
queryset=WirelessLAN.objects.all(), queryset=WirelessLAN.objects.all(),
widget=forms.MultipleHiddenInput widget=forms.MultipleHiddenInput
) )
group = DynamicModelChoiceField(
queryset=WirelessLANGroup.objects.all(),
required=False
)
vlan = DynamicModelChoiceField( vlan = DynamicModelChoiceField(
queryset=VLAN.objects.all(), queryset=VLAN.objects.all(),
required=False, required=False,
@ -31,7 +54,7 @@ class WirelessLANBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldMode
) )
class Meta: class Meta:
nullable_fields = ['vlan', 'ssid', 'description'] nullable_fields = ['ssid', 'group', 'vlan', 'description']
class WirelessLinkBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldModelBulkEditForm): class WirelessLinkBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldModelBulkEditForm):

View File

@ -2,16 +2,37 @@ from dcim.choices import LinkStatusChoices
from dcim.models import Interface from dcim.models import Interface
from extras.forms import CustomFieldModelCSVForm from extras.forms import CustomFieldModelCSVForm
from ipam.models import VLAN from ipam.models import VLAN
from utilities.forms import CSVChoiceField, CSVModelChoiceField from utilities.forms import CSVChoiceField, CSVModelChoiceField, SlugField
from wireless.models import * from wireless.models import *
__all__ = ( __all__ = (
'WirelessLANCSVForm', 'WirelessLANCSVForm',
'WirelessLANGroupCSVForm',
'WirelessLinkCSVForm', '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): class WirelessLANCSVForm(CustomFieldModelCSVForm):
group = CSVModelChoiceField(
queryset=WirelessLANGroup.objects.all(),
required=False,
to_field_name='name',
help_text='Assigned group'
)
vlan = CSVModelChoiceField( vlan = CSVModelChoiceField(
queryset=VLAN.objects.all(), queryset=VLAN.objects.all(),
to_field_name='name', to_field_name='name',
@ -20,7 +41,7 @@ class WirelessLANCSVForm(CustomFieldModelCSVForm):
class Meta: class Meta:
model = WirelessLAN model = WirelessLAN
fields = ('ssid', 'description', 'vlan') fields = ('ssid', 'group', 'description', 'vlan')
class WirelessLinkCSVForm(CustomFieldModelCSVForm): class WirelessLinkCSVForm(CustomFieldModelCSVForm):

View File

@ -3,19 +3,38 @@ from django.utils.translation import gettext as _
from dcim.choices import LinkStatusChoices from dcim.choices import LinkStatusChoices
from extras.forms import CustomFieldModelFilterForm 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 * from wireless.models import *
__all__ = ( __all__ = (
'WirelessLANFilterForm', 'WirelessLANFilterForm',
'WirelessLANGroupFilterForm',
'WirelessLinkFilterForm', '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): class WirelessLANFilterForm(BootstrapMixin, CustomFieldModelFilterForm):
model = WirelessLAN model = WirelessLAN
field_groups = [ field_groups = [
['q', 'tag'], ('q', 'tag'),
('group_id',),
] ]
q = forms.CharField( q = forms.CharField(
required=False, required=False,
@ -26,6 +45,13 @@ class WirelessLANFilterForm(BootstrapMixin, CustomFieldModelFilterForm):
required=False, required=False,
label='SSID' label='SSID'
) )
group_id = DynamicModelMultipleChoiceField(
queryset=WirelessLANGroup.objects.all(),
required=False,
null_option='None',
label=_('Group'),
fetch_trigger='open'
)
tag = TagFilterField(model) tag = TagFilterField(model)

View File

@ -2,16 +2,37 @@ from dcim.models import Interface
from extras.forms import CustomFieldModelForm from extras.forms import CustomFieldModelForm
from extras.models import Tag from extras.models import Tag
from ipam.models import VLAN 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 * from wireless.models import *
__all__ = ( __all__ = (
'WirelessLANForm', 'WirelessLANForm',
'WirelessLANGroupForm',
'WirelessLinkForm', '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): class WirelessLANForm(BootstrapMixin, CustomFieldModelForm):
group = DynamicModelChoiceField(
queryset=WirelessLANGroup.objects.all(),
required=False
)
vlan = DynamicModelChoiceField( vlan = DynamicModelChoiceField(
queryset=VLAN.objects.all(), queryset=VLAN.objects.all(),
required=False required=False
@ -24,10 +45,10 @@ class WirelessLANForm(BootstrapMixin, CustomFieldModelForm):
class Meta: class Meta:
model = WirelessLAN model = WirelessLAN
fields = [ fields = [
'ssid', 'description', 'vlan', 'tags', 'ssid', 'group', 'description', 'vlan', 'tags',
] ]
fieldsets = ( fieldsets = (
('Wireless LAN', ('ssid', 'description', 'tags')), ('Wireless LAN', ('ssid', 'group', 'description', 'tags')),
('VLAN', ('vlan',)), ('VLAN', ('vlan',)),
) )

View File

@ -7,3 +7,9 @@ from .types import *
class WirelessQuery(graphene.ObjectType): class WirelessQuery(graphene.ObjectType):
wirelesslan = ObjectField(WirelessLANType) wirelesslan = ObjectField(WirelessLANType)
wirelesslan_list = ObjectListField(WirelessLANType) wirelesslan_list = ObjectListField(WirelessLANType)
wirelesslangroup = ObjectField(WirelessLANGroupType)
wirelesslangroup_list = ObjectListField(WirelessLANGroupType)
wirelesslink = ObjectField(WirelessLinkType)
wirelesslink_list = ObjectListField(WirelessLinkType)

View File

@ -3,10 +3,19 @@ from netbox.graphql.types import ObjectType
__all__ = ( __all__ = (
'WirelessLANType', 'WirelessLANType',
'WirelessLANGroupType',
'WirelessLinkType', 'WirelessLinkType',
) )
class WirelessLANGroupType(ObjectType):
class Meta:
model = models.WirelessLANGroup
fields = '__all__'
filterset_class = filtersets.WirelessLANGroupFilterSet
class WirelessLANType(ObjectType): class WirelessLANType(ObjectType):
class Meta: class Meta:

View File

@ -1,8 +1,7 @@
# Generated by Django 3.2.8 on 2021-10-13 13:44
import django.core.serializers.json import django.core.serializers.json
from django.db import migrations, models from django.db import migrations, models
import django.db.models.deletion import django.db.models.deletion
import mptt.fields
import taggit.managers import taggit.managers
@ -17,6 +16,27 @@ class Migration(migrations.Migration):
] ]
operations = [ 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( migrations.CreateModel(
name='WirelessLAN', name='WirelessLAN',
fields=[ fields=[
@ -25,6 +45,7 @@ class Migration(migrations.Migration):
('custom_field_data', models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder)), ('custom_field_data', models.JSONField(blank=True, default=dict, encoder=django.core.serializers.json.DjangoJSONEncoder)),
('id', models.BigAutoField(primary_key=True, serialize=False)), ('id', models.BigAutoField(primary_key=True, serialize=False)),
('ssid', models.CharField(max_length=32)), ('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)), ('description', models.CharField(blank=True, max_length=200)),
('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')), ('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')), ('vlan', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='ipam.vlan')),

View File

@ -1,20 +1,58 @@
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.db import models from django.db import models
from django.urls import reverse from django.urls import reverse
from mptt.models import MPTTModel, TreeForeignKey
from dcim.choices import LinkStatusChoices from dcim.choices import LinkStatusChoices
from dcim.constants import WIRELESS_IFACE_TYPES from dcim.constants import WIRELESS_IFACE_TYPES
from extras.utils import extras_features 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 utilities.querysets import RestrictedQuerySet
from .constants import SSID_MAX_LENGTH from .constants import SSID_MAX_LENGTH
__all__ = ( __all__ = (
'WirelessLAN', 'WirelessLAN',
'WirelessLANGroup',
'WirelessLink', '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') @extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class WirelessLAN(PrimaryModel): class WirelessLAN(PrimaryModel):
""" """
@ -24,6 +62,13 @@ class WirelessLAN(PrimaryModel):
max_length=SSID_MAX_LENGTH, max_length=SSID_MAX_LENGTH,
verbose_name='SSID' 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( vlan = models.ForeignKey(
to='ipam.VLAN', to='ipam.VLAN',
on_delete=models.PROTECT, on_delete=models.PROTECT,
@ -100,7 +145,7 @@ class WirelessLink(PrimaryModel):
objects = RestrictedQuerySet.as_manager() objects = RestrictedQuerySet.as_manager()
clone_fields = ('ssid', 'status') clone_fields = ('ssid', 'group', 'status')
class Meta: class Meta:
ordering = ['pk'] ordering = ['pk']

View File

@ -1,14 +1,35 @@
import django_tables2 as tables import django_tables2 as tables
from utilities.tables import (
BaseTable, ButtonsColumn, ChoiceFieldColumn, LinkedCountColumn, MPTTColumn, TagColumn, ToggleColumn,
)
from .models import * from .models import *
from utilities.tables import BaseTable, ChoiceFieldColumn, TagColumn, ToggleColumn
__all__ = ( __all__ = (
'WirelessLANTable', 'WirelessLANTable',
'WirelessLANGroupTable',
'WirelessLinkTable', '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): class WirelessLANTable(BaseTable):
pk = ToggleColumn() pk = ToggleColumn()
ssid = tables.Column( ssid = tables.Column(

View File

@ -7,6 +7,17 @@ from .models import *
app_name = 'wireless' app_name = 'wireless'
urlpatterns = ( 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/<int:pk>/', views.WirelessLANGroupView.as_view(), name='wirelesslangroup'),
path('wireless-lan-groups/<int:pk>/edit/', views.WirelessLANGroupEditView.as_view(), name='wirelesslangroup_edit'),
path('wireless-lan-groups/<int:pk>/delete/', views.WirelessLANGroupDeleteView.as_view(), name='wirelesslangroup_delete'),
path('wireless-lan-groups/<int:pk>/changelog/', ObjectChangeLogView.as_view(), name='wirelesslangroup_changelog', kwargs={'model': WirelessLANGroup}),
# Wireless LANs # Wireless LANs
path('wireless-lans/', views.WirelessLANListView.as_view(), name='wirelesslan_list'), path('wireless-lans/', views.WirelessLANListView.as_view(), name='wirelesslan_list'),
path('wireless-lans/add/', views.WirelessLANEditView.as_view(), name='wirelesslan_add'), path('wireless-lans/add/', views.WirelessLANEditView.as_view(), name='wirelesslan_add'),

View File

@ -1,8 +1,81 @@
from netbox.views import generic from netbox.views import generic
from utilities.tables import paginate_table
from . import filtersets, forms, tables from . import filtersets, forms, tables
from .models import * 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 # Wireless LANs
# #