mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
Add WirelessLANGroup model
This commit is contained in:
@ -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'),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -13,6 +13,16 @@
|
||||
<th scope="row">SSID</th>
|
||||
<td>{{ object.ssid }}</td>
|
||||
</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>
|
||||
<th scope="row">Description</th>
|
||||
<td>{{ object.description|placeholder }}</td>
|
||||
|
72
netbox/templates/wireless/wirelesslangroup.html
Normal file
72
netbox/templates/wireless/wirelesslangroup.html
Normal 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">—</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 %}
|
@ -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')
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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
|
||||
|
@ -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',
|
||||
|
@ -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):
|
||||
|
@ -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):
|
||||
|
@ -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)
|
||||
|
||||
|
||||
|
@ -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',)),
|
||||
)
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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:
|
||||
|
@ -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')),
|
||||
|
@ -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']
|
||||
|
@ -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(
|
||||
|
@ -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/<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
|
||||
path('wireless-lans/', views.WirelessLANListView.as_view(), name='wirelesslan_list'),
|
||||
path('wireless-lans/add/', views.WirelessLANEditView.as_view(), name='wirelesslan_add'),
|
||||
|
@ -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
|
||||
#
|
||||
|
Reference in New Issue
Block a user