Add WirelessLink model

This commit is contained in:
jeremystretch 2021-10-13 09:46:17 -04:00
parent 5271680483
commit 90e9f34494
21 changed files with 458 additions and 58 deletions

View File

@ -1,10 +1,11 @@
# Generated by Django 3.2.8 on 2021-10-13 13:44
from django.db import migrations, models from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
('wireless', '0001_initial'),
('dcim', '0135_location_tenant'), ('dcim', '0135_location_tenant'),
] ]
@ -19,9 +20,4 @@ class Migration(migrations.Migration):
name='rf_channel_width', name='rf_channel_width',
field=models.PositiveSmallIntegerField(blank=True, null=True), field=models.PositiveSmallIntegerField(blank=True, null=True),
), ),
migrations.AddField(
model_name='interface',
name='wireless_lans',
field=models.ManyToManyField(blank=True, related_name='interfaces', to='wireless.WirelessLAN'),
),
] ]

View File

@ -0,0 +1,19 @@
# Generated by Django 3.2.8 on 2021-10-13 13:44
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('dcim', '0136_wireless'),
('wireless', '0001_wireless'),
]
operations = [
migrations.AddField(
model_name='interface',
name='wireless_lans',
field=models.ManyToManyField(blank=True, related_name='interfaces', to='wireless.WirelessLAN'),
),
]

View File

@ -196,6 +196,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']),
), ),
), ),
), ),

View File

@ -0,0 +1,20 @@
<table class="table table-hover panel-body attr-table">
<tr>
<td>Device</td>
<td>
<a href="{{ interface.device.get_absolute_url }}">{{ interface.device }}</a>
</td>
</tr>
<tr>
<td>Interface</td>
<td>
<a href="{{ interface.get_absolute_url }}">{{ interface }}</a>
</td>
</tr>
<tr>
<td>Type</td>
<td>
{{ interface.get_type_display }}
</td>
</tr>
</table>

View File

@ -30,7 +30,7 @@
</table> </table>
</div> </div>
</div> </div>
{% include 'extras/inc/tags_panel.html' with tags=object.tags.all url='dcim:site_list' %} {% include 'extras/inc/tags_panel.html' with tags=object.tags.all url='wireless:wirelesslan_list' %}
{% plugin_left_page object %} {% plugin_left_page object %}
</div> </div>
<div class="col col-md-6"> <div class="col col-md-6">

View File

@ -0,0 +1,48 @@
{% 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">Interface A</h5>
<div class="card-body">
{% include 'wireless/inc/wirelesslink_interface.html' with interface=object.interface_a %}
</div>
</div>
<div class="card">
<h5 class="card-header">Link Properties</h5>
<div class="card-body">
<table class="table table-hover attr-table">
<tr>
<th scope="row">SSID</th>
<td>{{ object.ssid|placeholder }}</td>
</tr>
<tr>
<th scope="row">Description</th>
<td>{{ object.description|placeholder }}</td>
</tr>
</table>
</div>
</div>
{% plugin_left_page object %}
</div>
<div class="col col-md-6">
<div class="card">
<h5 class="card-header">Interface B</h5>
<div class="card-body">
{% include 'wireless/inc/wirelesslink_interface.html' with interface=object.interface_b %}
</div>
</div>
{% include 'inc/custom_fields_panel.html' %}
{% include 'extras/inc/tags_panel.html' with tags=object.tags.all url='wireless:wirelesslink_list' %}
{% plugin_right_page object %}
</div>
</div>
<div class="row">
<div class="col col-md-12">
{% plugin_full_width_page object %}
</div>
</div>
{% endblock %}

View File

@ -5,12 +5,21 @@ from wireless.models import *
__all__ = ( __all__ = (
'NestedWirelessLANSerializer', 'NestedWirelessLANSerializer',
'NestedWirelessLinkSerializer',
) )
class NestedWirelessLANSerializer(WritableNestedSerializer): class NestedWirelessLANSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='wireless-api:ssid-detail') url = serializers.HyperlinkedIdentityField(view_name='wireless-api:wirelesslan-detail')
class Meta: class Meta:
model = WirelessLAN model = WirelessLAN
fields = ['id', 'url', 'display', 'ssid'] fields = ['id', 'url', 'display', 'ssid']
class NestedWirelessLinkSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='wireless-api:wirelesslink-detail')
class Meta:
model = WirelessLink
fields = ['id', 'url', 'display', 'ssid']

View File

@ -1,16 +1,19 @@
from rest_framework import serializers from rest_framework import serializers
from dcim.api.serializers import NestedInterfaceSerializer
from ipam.api.serializers import NestedVLANSerializer from ipam.api.serializers import NestedVLANSerializer
from netbox.api.serializers import PrimaryModelSerializer from netbox.api.serializers import PrimaryModelSerializer
from wireless.models import * from wireless.models import *
from .nested_serializers import *
__all__ = ( __all__ = (
'WirelessLANSerializer', 'WirelessLANSerializer',
'WirelessLinkSerializer',
) )
class WirelessLANSerializer(PrimaryModelSerializer): class WirelessLANSerializer(PrimaryModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='wireless-api:ssid-detail') url = serializers.HyperlinkedIdentityField(view_name='wireless-api:wirelesslan-detail')
vlan = NestedVLANSerializer(required=False, allow_null=True) vlan = NestedVLANSerializer(required=False, allow_null=True)
class Meta: class Meta:
@ -18,3 +21,15 @@ class WirelessLANSerializer(PrimaryModelSerializer):
fields = [ fields = [
'id', 'url', 'display', 'ssid', 'description', 'vlan', 'id', 'url', 'display', 'ssid', 'description', 'vlan',
] ]
class WirelessLinkSerializer(PrimaryModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='wireless-api:wirelesslink-detail')
interface_a = NestedInterfaceSerializer()
interface_b = NestedInterfaceSerializer()
class Meta:
model = WirelessLAN
fields = [
'id', 'url', 'display', 'interface_a', 'interface_b', 'ssid', 'description',
]

View File

@ -6,6 +6,7 @@ router = OrderedDefaultRouter()
router.APIRootView = views.WirelessRootView router.APIRootView = views.WirelessRootView
router.register('wireless-lans', views.WirelessLANViewSet) router.register('wireless-lans', views.WirelessLANViewSet)
router.register('wireless-links', views.WirelessLinkViewSet)
app_name = 'wireless-api' app_name = 'wireless-api'
urlpatterns = router.urls urlpatterns = router.urls

View File

@ -14,11 +14,13 @@ class WirelessRootView(APIRootView):
return 'Wireless' return 'Wireless'
#
# Providers
#
class WirelessLANViewSet(CustomFieldModelViewSet): class WirelessLANViewSet(CustomFieldModelViewSet):
queryset = WirelessLAN.objects.prefetch_related('tags') queryset = WirelessLAN.objects.prefetch_related('vlan', 'tags')
serializer_class = serializers.WirelessLANSerializer serializer_class = serializers.WirelessLANSerializer
filterset_class = filtersets.WirelessLANFilterSet filterset_class = filtersets.WirelessLANFilterSet
class WirelessLinkViewSet(CustomFieldModelViewSet):
queryset = WirelessLink.objects.prefetch_related('interface_a', 'interface_b', 'tags')
serializer_class = serializers.WirelessLinkSerializer
filterset_class = filtersets.WirelessLinkFilterSet

View File

@ -7,6 +7,7 @@ from .models import *
__all__ = ( __all__ = (
'WirelessLANFilterSet', 'WirelessLANFilterSet',
'WirelessLinkFilterSet',
) )
@ -29,3 +30,24 @@ class WirelessLANFilterSet(PrimaryModelFilterSet):
Q(description__icontains=value) Q(description__icontains=value)
) )
return queryset.filter(qs_filter) return queryset.filter(qs_filter)
class WirelessLinkFilterSet(PrimaryModelFilterSet):
q = django_filters.CharFilter(
method='search',
label='Search',
)
tag = TagFilter()
class Meta:
model = WirelessLink
fields = ['id', 'ssid']
def search(self, queryset, name, value):
if not value.strip():
return queryset
qs_filter = (
Q(ssid__icontains=value) |
Q(description__icontains=value)
)
return queryset.filter(qs_filter)

View File

@ -4,9 +4,11 @@ from dcim.models import *
from extras.forms import AddRemoveTagsForm, CustomFieldModelBulkEditForm from extras.forms import AddRemoveTagsForm, CustomFieldModelBulkEditForm
from ipam.models import VLAN from ipam.models import VLAN
from utilities.forms import BootstrapMixin, DynamicModelChoiceField from utilities.forms import BootstrapMixin, DynamicModelChoiceField
from wireless.constants import SSID_MAX_LENGTH
__all__ = ( __all__ = (
'WirelessLANBulkEditForm', 'WirelessLANBulkEditForm',
'WirelessLinkBulkEditForm',
) )
@ -19,11 +21,30 @@ class WirelessLANBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldMode
queryset=VLAN.objects.all(), queryset=VLAN.objects.all(),
required=False, required=False,
) )
ssid = forms.CharField(
max_length=SSID_MAX_LENGTH,
required=False
)
description = forms.CharField( description = forms.CharField(
required=False required=False
) )
class Meta: class Meta:
nullable_fields = [ nullable_fields = ['vlan', 'ssid', 'description']
'vlan', 'description',
]
class WirelessLinkBulkEditForm(BootstrapMixin, AddRemoveTagsForm, CustomFieldModelBulkEditForm):
pk = forms.ModelMultipleChoiceField(
queryset=PowerFeed.objects.all(),
widget=forms.MultipleHiddenInput
)
ssid = forms.CharField(
max_length=SSID_MAX_LENGTH,
required=False
)
description = forms.CharField(
required=False
)
class Meta:
nullable_fields = ['ssid', 'description']

View File

@ -1,10 +1,12 @@
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 CSVModelChoiceField from utilities.forms import CSVModelChoiceField
from wireless.models import WirelessLAN from wireless.models import *
__all__ = ( __all__ = (
'WirelessLANCSVForm', 'WirelessLANCSVForm',
'WirelessLinkCSVForm',
) )
@ -18,3 +20,16 @@ class WirelessLANCSVForm(CustomFieldModelCSVForm):
class Meta: class Meta:
model = WirelessLAN model = WirelessLAN
fields = ('ssid', 'description', 'vlan') fields = ('ssid', 'description', 'vlan')
class WirelessLinkCSVForm(CustomFieldModelCSVForm):
interface_a = CSVModelChoiceField(
queryset=Interface.objects.all()
)
interface_b = CSVModelChoiceField(
queryset=Interface.objects.all()
)
class Meta:
model = WirelessLink
fields = ('interface_a', 'interface_b', 'ssid', 'description')

View File

@ -3,7 +3,12 @@ from django.utils.translation import gettext as _
from extras.forms import CustomFieldModelFilterForm from extras.forms import CustomFieldModelFilterForm
from utilities.forms import BootstrapMixin, TagFilterField from utilities.forms import BootstrapMixin, TagFilterField
from .models import WirelessLAN from wireless.models import *
__all__ = (
'WirelessLANFilterForm',
'WirelessLinkFilterForm',
)
class WirelessLANFilterForm(BootstrapMixin, CustomFieldModelFilterForm): class WirelessLANFilterForm(BootstrapMixin, CustomFieldModelFilterForm):
@ -16,4 +21,25 @@ class WirelessLANFilterForm(BootstrapMixin, CustomFieldModelFilterForm):
widget=forms.TextInput(attrs={'placeholder': _('All Fields')}), widget=forms.TextInput(attrs={'placeholder': _('All Fields')}),
label=_('Search') label=_('Search')
) )
ssid = forms.CharField(
required=False,
label='SSID'
)
tag = TagFilterField(model)
class WirelessLinkFilterForm(BootstrapMixin, CustomFieldModelFilterForm):
model = WirelessLink
field_groups = [
['q', 'tag'],
]
q = forms.CharField(
required=False,
widget=forms.TextInput(attrs={'placeholder': _('All Fields')}),
label=_('Search')
)
ssid = forms.CharField(
required=False,
label='SSID'
)
tag = TagFilterField(model) tag = TagFilterField(model)

View File

@ -1,11 +1,13 @@
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 from utilities.forms import BootstrapMixin, DynamicModelChoiceField, DynamicModelMultipleChoiceField
from wireless.models import WirelessLAN from wireless.models import *
__all__ = ( __all__ = (
'WirelessLANForm', 'WirelessLANForm',
'WirelessLinkForm',
) )
@ -28,3 +30,28 @@ class WirelessLANForm(BootstrapMixin, CustomFieldModelForm):
('Wireless LAN', ('ssid', 'description', 'tags')), ('Wireless LAN', ('ssid', 'description', 'tags')),
('VLAN', ('vlan',)), ('VLAN', ('vlan',)),
) )
class WirelessLinkForm(BootstrapMixin, CustomFieldModelForm):
interface_a = DynamicModelChoiceField(
queryset=Interface.objects.all(),
query_params={
'kind': 'wireless'
}
)
interface_b = DynamicModelChoiceField(
queryset=Interface.objects.all(),
query_params={
'kind': 'wireless'
}
)
tags = DynamicModelMultipleChoiceField(
queryset=Tag.objects.all(),
required=False
)
class Meta:
model = WirelessLink
fields = [
'interface_a', 'interface_b', 'ssid', 'description', 'tags',
]

View File

@ -1,34 +0,0 @@
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 = [
('ipam', '0050_iprange'),
('extras', '0062_clear_secrets_changelog'),
]
operations = [
migrations.CreateModel(
name='WirelessLAN',
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)),
('ssid', 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': 'Wireless LAN',
'ordering': ('ssid', 'pk'),
},
),
]

View File

@ -0,0 +1,57 @@
# 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 taggit.managers
class Migration(migrations.Migration):
initial = True
dependencies = [
('dcim', '0136_wireless'),
('extras', '0062_clear_secrets_changelog'),
('ipam', '0050_iprange'),
]
operations = [
migrations.CreateModel(
name='WirelessLAN',
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)),
('ssid', 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': 'Wireless LAN',
'ordering': ('ssid', 'pk'),
},
),
migrations.CreateModel(
name='WirelessLink',
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)),
('ssid', models.CharField(blank=True, max_length=32)),
('description', models.CharField(blank=True, max_length=200)),
('_interface_a_device', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='+', to='dcim.device')),
('_interface_b_device', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='+', to='dcim.device')),
('interface_a', models.ForeignKey(limit_choices_to={'type__in': ['ieee802.11a', 'ieee802.11g', 'ieee802.11n', 'ieee802.11ac', 'ieee802.11ad', 'ieee802.11ax']}, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='dcim.interface')),
('interface_b', models.ForeignKey(limit_choices_to={'type__in': ['ieee802.11a', 'ieee802.11g', 'ieee802.11n', 'ieee802.11ac', 'ieee802.11ad', 'ieee802.11ax']}, on_delete=django.db.models.deletion.PROTECT, related_name='+', to='dcim.interface')),
('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')),
],
options={
'ordering': ['pk'],
'unique_together': {('interface_a', 'interface_b')},
},
),
]

View File

@ -6,19 +6,22 @@ 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, PrimaryModel
from utilities.querysets import RestrictedQuerySet from utilities.querysets import RestrictedQuerySet
from .constants import SSID_MAX_LENGTH
__all__ = ( __all__ = (
'WirelessLAN', 'WirelessLAN',
'WirelessLink',
) )
@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):
""" """
A service set identifier belonging to a wireless network. A wireless network formed among an arbitrary number of access point and clients.
""" """
ssid = models.CharField( ssid = models.CharField(
max_length=32 max_length=SSID_MAX_LENGTH,
verbose_name='SSID'
) )
vlan = models.ForeignKey( vlan = models.ForeignKey(
to='ipam.VLAN', to='ipam.VLAN',
@ -42,4 +45,78 @@ class WirelessLAN(PrimaryModel):
return self.ssid return self.ssid
def get_absolute_url(self): def get_absolute_url(self):
return reverse('wireless:ssid', args=[self.pk]) return reverse('wireless:wirelesslan', args=[self.pk])
@extras_features('custom_fields', 'custom_links', 'export_templates', 'tags', 'webhooks')
class WirelessLink(PrimaryModel):
"""
A point-to-point connection between two wireless Interfaces.
"""
interface_a = models.ForeignKey(
to='dcim.Interface',
limit_choices_to={'type__in': WIRELESS_IFACE_TYPES},
on_delete=models.PROTECT,
related_name='+'
)
interface_b = models.ForeignKey(
to='dcim.Interface',
limit_choices_to={'type__in': WIRELESS_IFACE_TYPES},
on_delete=models.PROTECT,
related_name='+'
)
ssid = models.CharField(
max_length=SSID_MAX_LENGTH,
blank=True,
verbose_name='SSID'
)
description = models.CharField(
max_length=200,
blank=True
)
# Cache the associated device for the A and B interfaces. This enables filtering of WirelessLinks by their
# associated Devices.
_interface_a_device = models.ForeignKey(
to='dcim.Device',
on_delete=models.CASCADE,
related_name='+',
blank=True,
null=True
)
_interface_b_device = models.ForeignKey(
to='dcim.Device',
on_delete=models.CASCADE,
related_name='+',
blank=True,
null=True
)
objects = RestrictedQuerySet.as_manager()
class Meta:
ordering = ['pk']
unique_together = ('interface_a', 'interface_b')
def get_absolute_url(self):
return reverse('wireless:wirelesslink', args=[self.pk])
def clean(self):
# Validate interface types
if self.interface_a.type not in WIRELESS_IFACE_TYPES:
raise ValidationError({
'interface_a': f"{self.interface_a.get_type_display()} is not a wireless interface."
})
if self.interface_b.type not in WIRELESS_IFACE_TYPES:
raise ValidationError({
'interface_a': f"{self.interface_b.get_type_display()} is not a wireless interface."
})
def save(self, *args, **kwargs):
# Store the parent Device for the A and B interfaces
self._interface_a_device = self.interface_a.device
self._interface_b_device = self.interface_b.device
super().save(*args, **kwargs)

View File

@ -1,10 +1,11 @@
import django_tables2 as tables import django_tables2 as tables
from .models import WirelessLAN from .models import *
from utilities.tables import BaseTable, TagColumn, ToggleColumn from utilities.tables import BaseTable, TagColumn, ToggleColumn
__all__ = ( __all__ = (
'WirelessLANTable', 'WirelessLANTable',
'WirelessLinkTable',
) )
@ -21,3 +22,25 @@ class WirelessLANTable(BaseTable):
model = WirelessLAN model = WirelessLAN
fields = ('pk', 'ssid', 'description', 'vlan') fields = ('pk', 'ssid', 'description', 'vlan')
default_columns = ('pk', 'ssid', 'description', 'vlan') default_columns = ('pk', 'ssid', 'description', 'vlan')
class WirelessLinkTable(BaseTable):
pk = ToggleColumn()
id = tables.Column(
linkify=True,
verbose_name='ID'
)
interface_a = tables.Column(
linkify=True
)
interface_b = tables.Column(
linkify=True
)
tags = TagColumn(
url_name='wireless:wirelesslink_list'
)
class Meta(BaseTable.Meta):
model = WirelessLink
fields = ('pk', 'id', 'interface_a', 'interface_b', 'ssid', 'description')
default_columns = ('pk', 'id', 'interface_a', 'interface_b', 'ssid', 'description')

View File

@ -19,4 +19,16 @@ urlpatterns = (
path('wireless-lans/<int:pk>/changelog/', ObjectChangeLogView.as_view(), name='wirelesslan_changelog', kwargs={'model': WirelessLAN}), path('wireless-lans/<int:pk>/changelog/', ObjectChangeLogView.as_view(), name='wirelesslan_changelog', kwargs={'model': WirelessLAN}),
path('wireless-lans/<int:pk>/journal/', ObjectJournalView.as_view(), name='wirelesslan_journal', kwargs={'model': WirelessLAN}), path('wireless-lans/<int:pk>/journal/', ObjectJournalView.as_view(), name='wirelesslan_journal', kwargs={'model': WirelessLAN}),
# Wireless links
path('wireless-links/', views.WirelessLinkListView.as_view(), name='wirelesslink_list'),
path('wireless-links/add/', views.WirelessLinkEditView.as_view(), name='wirelesslink_add'),
path('wireless-links/import/', views.WirelessLinkBulkImportView.as_view(), name='wirelesslink_import'),
path('wireless-links/edit/', views.WirelessLinkBulkEditView.as_view(), name='wirelesslink_bulk_edit'),
path('wireless-links/delete/', views.WirelessLinkBulkDeleteView.as_view(), name='wirelesslink_bulk_delete'),
path('wireless-links/<int:pk>/', views.WirelessLinkView.as_view(), name='wirelesslink'),
path('wireless-links/<int:pk>/edit/', views.WirelessLinkEditView.as_view(), name='wirelesslink_edit'),
path('wireless-links/<int:pk>/delete/', views.WirelessLinkDeleteView.as_view(), name='wirelesslink_delete'),
path('wireless-links/<int:pk>/changelog/', ObjectChangeLogView.as_view(), name='wirelesslink_changelog', kwargs={'model': WirelessLink}),
path('wireless-links/<int:pk>/journal/', ObjectJournalView.as_view(), name='wirelesslink_journal', kwargs={'model': WirelessLink}),
) )

View File

@ -44,3 +44,46 @@ class WirelessLANBulkDeleteView(generic.BulkDeleteView):
queryset = WirelessLAN.objects.all() queryset = WirelessLAN.objects.all()
filterset = filtersets.WirelessLANFilterSet filterset = filtersets.WirelessLANFilterSet
table = tables.WirelessLANTable table = tables.WirelessLANTable
#
# Wireless Links
#
class WirelessLinkListView(generic.ObjectListView):
queryset = WirelessLink.objects.all()
filterset = filtersets.WirelessLinkFilterSet
filterset_form = forms.WirelessLinkFilterForm
table = tables.WirelessLinkTable
class WirelessLinkView(generic.ObjectView):
queryset = WirelessLink.objects.all()
class WirelessLinkEditView(generic.ObjectEditView):
queryset = WirelessLink.objects.all()
model_form = forms.WirelessLinkForm
class WirelessLinkDeleteView(generic.ObjectDeleteView):
queryset = WirelessLink.objects.all()
class WirelessLinkBulkImportView(generic.BulkImportView):
queryset = WirelessLink.objects.all()
model_form = forms.WirelessLinkCSVForm
table = tables.WirelessLinkTable
class WirelessLinkBulkEditView(generic.BulkEditView):
queryset = WirelessLink.objects.all()
filterset = filtersets.WirelessLinkFilterSet
table = tables.WirelessLinkTable
form = forms.WirelessLinkBulkEditForm
class WirelessLinkBulkDeleteView(generic.BulkDeleteView):
queryset = WirelessLink.objects.all()
filterset = filtersets.WirelessLinkFilterSet
table = tables.WirelessLinkTable