Add Coordinate models, forms, views, templates,...
This commit is contained in:
@@ -2,7 +2,7 @@ from dcim.models import Device, DeviceRole
|
||||
from rest_framework.serializers import ModelSerializer
|
||||
from netbox.api.serializers import NetBoxModelSerializer
|
||||
|
||||
from netbox_topology_views.models import RoleImage, IndividualOptions
|
||||
from netbox_topology_views.models import RoleImage, IndividualOptions, CoordinateGroups, Coordinates
|
||||
|
||||
|
||||
class TopologyDummySerializer(ModelSerializer):
|
||||
@@ -22,6 +22,16 @@ class DeviceRoleSerializer(ModelSerializer):
|
||||
model = DeviceRole
|
||||
fields = ("name", "slug", "color", "vm_role", "description")
|
||||
|
||||
class CoordinateGroupsSerializer(NetBoxModelSerializer):
|
||||
class Meta:
|
||||
model = CoordinateGroups
|
||||
fields = ("name", "description")
|
||||
|
||||
class CoordinatesSerializer(NetBoxModelSerializer):
|
||||
class Meta:
|
||||
model = Coordinates
|
||||
fields = ("x", "y")
|
||||
|
||||
class IndividualOptionsSerializer(NetBoxModelSerializer):
|
||||
class Meta:
|
||||
model = IndividualOptions
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import django_filters
|
||||
from dcim.choices import DeviceStatusChoices
|
||||
from dcim.models import Device, DeviceRole, Location, Rack, Region, Site
|
||||
from .models import Coordinates
|
||||
from django.db.models import Q
|
||||
from netbox.filtersets import NetBoxModelFilterSet
|
||||
from tenancy.filtersets import TenancyFilterSet
|
||||
@@ -53,3 +54,15 @@ class DeviceFilterSet(TenancyFilterSet, NetBoxModelFilterSet):
|
||||
return queryset
|
||||
qs_filter = Q(name__icontains=value)
|
||||
return queryset.filter(qs_filter)
|
||||
|
||||
class CoordinateFilterSet(NetBoxModelFilterSet):
|
||||
class Meta:
|
||||
model = Coordinates
|
||||
fields = ('id', 'group', 'device', 'x', 'y')
|
||||
|
||||
def search(self, queryset, name, value):
|
||||
"""Perform the filtered search."""
|
||||
if not value.strip():
|
||||
return queryset
|
||||
qs_filter = Q(group__icontains=value | Q(device__icontains=value))
|
||||
return queryset.filter(qs_filter)
|
||||
@@ -15,12 +15,13 @@ from django.conf import settings
|
||||
from netbox.forms import NetBoxModelFilterSetForm, NetBoxModelForm
|
||||
from utilities.forms.fields import (
|
||||
TagFilterField,
|
||||
DynamicModelChoiceField,
|
||||
DynamicModelMultipleChoiceField,
|
||||
MultipleChoiceField
|
||||
)
|
||||
|
||||
|
||||
from .models import IndividualOptions
|
||||
from .models import IndividualOptions, CoordinateGroups, Coordinates
|
||||
|
||||
class DeviceFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
|
||||
model = Device
|
||||
@@ -141,6 +142,55 @@ class DeviceFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
|
||||
label =_("Show Wireless Links"), required=False, initial=False
|
||||
)
|
||||
|
||||
class CoordinateGroupsForm(NetBoxModelForm):
|
||||
fieldsets = (
|
||||
('Group Details', ('name', 'description')),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = CoordinateGroups
|
||||
fields = ('name', 'description')
|
||||
|
||||
class CoordinatesForm(NetBoxModelForm):
|
||||
fieldsets = (
|
||||
('Coordinates', ('group', 'device', 'x', 'y')),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = Coordinates
|
||||
fields = ('group', 'device', 'x', 'y')
|
||||
|
||||
class CoordinatesFilterForm(NetBoxModelFilterSetForm):
|
||||
model = Coordinates
|
||||
|
||||
group = forms.ModelMultipleChoiceField(
|
||||
queryset=CoordinateGroups.objects.all(),
|
||||
required=False
|
||||
)
|
||||
|
||||
device = DynamicModelChoiceField(
|
||||
queryset=Device.objects.all(),
|
||||
required=False
|
||||
)
|
||||
id = DynamicModelMultipleChoiceField(
|
||||
queryset=Device.objects.all(),
|
||||
required=False,
|
||||
label=_("Device"),
|
||||
query_params={
|
||||
"location_id": "$location_id",
|
||||
"region_id": "$region_id",
|
||||
"site_id": "$site_id",
|
||||
"role_id": "$device_role_id",
|
||||
},
|
||||
)
|
||||
x = forms.IntegerField(
|
||||
required=False
|
||||
)
|
||||
|
||||
y = forms.IntegerField(
|
||||
required=False
|
||||
)
|
||||
|
||||
class IndividualOptionsForm(NetBoxModelForm):
|
||||
fieldsets = (
|
||||
(
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
# Generated by Django 4.1.8 on 2023-05-01 08:21
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import taggit.managers
|
||||
import utilities.json
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('dcim', '0171_cabletermination_change_logging'),
|
||||
('extras', '0092_delete_jobresult'),
|
||||
('netbox_topology_views', '0003_individualoptions_show_neighbors'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='CoordinateGroups',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)),
|
||||
('created', models.DateTimeField(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=utilities.json.CustomFieldJSONEncoder)),
|
||||
('name', models.CharField(max_length=100, unique=True)),
|
||||
('description', models.CharField(blank=True, max_length=255)),
|
||||
('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')),
|
||||
],
|
||||
options={
|
||||
'ordering': ['name'],
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Coordinates',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)),
|
||||
('created', models.DateTimeField(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=utilities.json.CustomFieldJSONEncoder)),
|
||||
('x', models.IntegerField()),
|
||||
('y', models.IntegerField()),
|
||||
('device', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='dcim.device')),
|
||||
('group', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='netbox_topology_views.coordinategroups')),
|
||||
('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')),
|
||||
],
|
||||
options={
|
||||
'ordering': ['group', 'device'],
|
||||
'unique_together': {('device', 'group')},
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -1,12 +1,13 @@
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
from dcim.models import DeviceRole
|
||||
from dcim.models import Device, DeviceRole
|
||||
from extras.models import Tag
|
||||
from django.conf import settings
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.db import models
|
||||
from django.templatetags.static import static
|
||||
from django.urls import reverse
|
||||
from netbox.models import NetBoxModel
|
||||
from netbox.models.features import (
|
||||
ChangeLoggingMixin,
|
||||
@@ -94,6 +95,63 @@ class RoleImage(ChangeLoggingMixin, ExportTemplatesMixin, WebhooksMixin):
|
||||
return self.get_default_image(dir)
|
||||
return static(f"/{self.image}")
|
||||
|
||||
class CoordinateGroups(NetBoxModel):
|
||||
"""
|
||||
A coordinate group is used to display the topology for a particular group.
|
||||
This allows different visualizations with the same devices.
|
||||
"""
|
||||
name = models.CharField(
|
||||
max_length=100,
|
||||
unique=True,
|
||||
)
|
||||
|
||||
description = models.CharField(
|
||||
max_length=255,
|
||||
blank = True,
|
||||
)
|
||||
|
||||
class Meta:
|
||||
ordering = ['name']
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse('plugins:netbox_topology_views:coordinategroups', args=[self.pk])
|
||||
|
||||
class Coordinates(NetBoxModel):
|
||||
"""
|
||||
Coordinates are being used to place devices in a topology view onto a certian
|
||||
position. Devices belong to one or more coordinate groups. They have to
|
||||
be unique together.
|
||||
"""
|
||||
device = models.ForeignKey(Device, on_delete=models.CASCADE)
|
||||
group = models.ForeignKey(CoordinateGroups, on_delete=models.CASCADE)
|
||||
|
||||
x = models.IntegerField(
|
||||
help_text='X-coordinate of the device (horizontal) on the canvas. '
|
||||
'Smaller values correspond to a position further up on the monitor.',
|
||||
)
|
||||
y = models.IntegerField(
|
||||
help_text='Y-coordinate of the device (vertical) on the canvas. '
|
||||
'Smaller values correspond to a position further to the left on the monitor.',
|
||||
)
|
||||
|
||||
class Meta:
|
||||
ordering = ['group', 'device']
|
||||
unique_together = ('device', 'group')
|
||||
|
||||
def __str__(self):
|
||||
return f'{self.x};{self.y}'
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse('plugins:netbox_topology_views:coordinates', args=[self.pk])
|
||||
|
||||
def set_xy_from_text_coords(self, coords: str):
|
||||
xy = coords.split(';')
|
||||
self.x = xy[0]
|
||||
self.y = xy[1]
|
||||
|
||||
class IndividualOptions(NetBoxModel):
|
||||
CHOICES = (
|
||||
('interface', 'interface'),
|
||||
|
||||
@@ -1,10 +1,35 @@
|
||||
from extras.plugins import PluginMenu, PluginMenuItem
|
||||
from extras.plugins import PluginMenu, PluginMenuItem, PluginMenuButton
|
||||
from utilities.choices import ButtonColorChoices
|
||||
|
||||
coordinategroups_buttons = [
|
||||
PluginMenuButton(
|
||||
link='plugins:netbox_topology_views:coordinategroups_add',
|
||||
title='Add',
|
||||
icon_class='mdi mdi-plus-thick',
|
||||
color=ButtonColorChoices.GREEN,
|
||||
)
|
||||
]
|
||||
|
||||
coordinates_buttons = [
|
||||
PluginMenuButton(
|
||||
link='plugins:netbox_topology_views:coordinates_add',
|
||||
title='Add',
|
||||
icon_class='mdi mdi-plus-thick',
|
||||
color=ButtonColorChoices.GREEN,
|
||||
)
|
||||
]
|
||||
|
||||
menu = PluginMenu(
|
||||
label='Topology Views',
|
||||
icon_class="mdi mdi-sitemap",
|
||||
groups=(
|
||||
('TOPOLOGY', (PluginMenuItem(link="plugins:netbox_topology_views:home", link_text="Topology"),),),
|
||||
('TOPOLOGY',
|
||||
(
|
||||
PluginMenuItem(link="plugins:netbox_topology_views:home", link_text="Topology"),
|
||||
PluginMenuItem(link="plugins:netbox_topology_views:coordinategroups_list", link_text="Coordinate Groups", buttons=coordinategroups_buttons),
|
||||
PluginMenuItem(link="plugins:netbox_topology_views:coordinates_list", link_text="Coordinates", buttons=coordinates_buttons),
|
||||
),
|
||||
),
|
||||
('PREFERENCES',
|
||||
(
|
||||
PluginMenuItem(link="plugins:netbox_topology_views:images", link_text="Images"),
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
from netbox.search import SearchIndex, register_search
|
||||
from .models import CoordinateGroups, Coordinates
|
||||
|
||||
@register_search
|
||||
class CoordinateGroupsIndex(SearchIndex):
|
||||
model = CoordinateGroups
|
||||
fields = (
|
||||
('name', 100),
|
||||
('description', 2000),
|
||||
)
|
||||
|
||||
@register_search
|
||||
class CoordinatesIndex(SearchIndex):
|
||||
model = Coordinates
|
||||
fields = (
|
||||
('group', 100),
|
||||
('device', 200),
|
||||
)
|
||||
@@ -0,0 +1,29 @@
|
||||
import django_tables2 as tables
|
||||
|
||||
from netbox.tables import NetBoxTable, ChoiceFieldColumn
|
||||
from .models import CoordinateGroups, Coordinates
|
||||
|
||||
class CoordinateGroupListTable(NetBoxTable):
|
||||
name = tables.Column(
|
||||
linkify=True
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
model = CoordinateGroups
|
||||
fields = ('pk', 'name', 'description')
|
||||
default_columns = ('name', 'description')
|
||||
|
||||
class CoordinateListTable(NetBoxTable):
|
||||
group = tables.Column(
|
||||
linkify=True
|
||||
)
|
||||
|
||||
device = tables.Column(
|
||||
linkify=True
|
||||
)
|
||||
|
||||
class Meta(NetBoxTable.Meta):
|
||||
model = Coordinates
|
||||
fields = ('pk', 'group', 'device', 'x', 'y')
|
||||
default_columns = ('id', 'group', 'device', 'x', 'y')
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
{% extends 'generic/object.html' %}
|
||||
{% load helpers %}
|
||||
{% load plugins %}
|
||||
{% load render_table from django_tables2 %}
|
||||
|
||||
{% block title %}Topology Views Coordinate Group{% endblock title %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row mb-3">
|
||||
<div class="col col-md-6">
|
||||
<div class="card">
|
||||
<h5 class="card-header">
|
||||
Coordinate 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>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{% plugin_left_page object %}
|
||||
</div>
|
||||
<div class="col col-md-6">
|
||||
{% include 'inc/panels/custom_fields.html' %}
|
||||
{% plugin_right_page object %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock content %}
|
||||
@@ -0,0 +1,3 @@
|
||||
{% extends 'generic/object_edit.html' %}
|
||||
|
||||
{% block title %}Add a new Coordinate Group{% endblock title %}
|
||||
@@ -0,0 +1,3 @@
|
||||
{% extends 'generic/object_edit.html' %}
|
||||
|
||||
{% block title %}Edit Coordinate Group{% endblock title %}
|
||||
@@ -0,0 +1,3 @@
|
||||
{% extends 'generic/object_list.html' %}
|
||||
|
||||
{% block title %}Coordinate Groups{% endblock title %}
|
||||
@@ -0,0 +1,43 @@
|
||||
{% extends 'generic/object.html' %}
|
||||
{% load helpers %}
|
||||
{% load plugins %}
|
||||
{% load render_table from django_tables2 %}
|
||||
|
||||
{% block title %}Topology Views Coordinates{% endblock title %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row mb-3">
|
||||
<div class="col col-md-6">
|
||||
<div class="card">
|
||||
<h5 class="card-header">
|
||||
Coordinates
|
||||
</h5>
|
||||
<div class="card-body">
|
||||
<table class="table table-hover attr-table">
|
||||
<tr>
|
||||
<th scope="row">Group</th>
|
||||
<td>{{ object.group }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Device</th>
|
||||
<td>{{ object.device }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">X-Coordinate</th>
|
||||
<td>{{ object.x }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Y-Coordinate</th>
|
||||
<td>{{ object.y }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{% plugin_left_page object %}
|
||||
</div>
|
||||
<div class="col col-md-6">
|
||||
{% include 'inc/panels/custom_fields.html' %}
|
||||
{% plugin_right_page object %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock content %}
|
||||
@@ -0,0 +1,3 @@
|
||||
{% extends 'generic/object_edit.html' %}
|
||||
|
||||
{% block title %}Add new Device Coordinates{% endblock title %}
|
||||
@@ -0,0 +1,3 @@
|
||||
{% extends 'generic/object_edit.html' %}
|
||||
|
||||
{% block title %}Edit Device Coordinates{% endblock title %}
|
||||
@@ -0,0 +1,3 @@
|
||||
{% extends 'generic/object_list.html' %}
|
||||
|
||||
{% block title %}Device Coordinates{% endblock title %}
|
||||
@@ -1,7 +1,7 @@
|
||||
from django.urls import path
|
||||
from django.views.generic.base import RedirectView
|
||||
|
||||
from . import views
|
||||
from . import models, views
|
||||
|
||||
# Define a list of URL patterns to be imported by NetBox. Each pattern maps a URL to
|
||||
# a specific view so that it can be accessed by users.
|
||||
@@ -10,4 +10,20 @@ urlpatterns = (
|
||||
path("topology/", views.TopologyHomeView.as_view(), name="home"),
|
||||
path("images/", views.TopologyImagesView.as_view(), name="images"),
|
||||
path("individualoptions/", views.TopologyIndividualOptionsView.as_view(), name="individualoptions"),
|
||||
|
||||
# Coordinate Group
|
||||
path("coordinate-groups/", views.CoordinateGroupListView.as_view(), name="coordinategroups_list"),
|
||||
path("coordinate-groups/add/", views.CoordinateGroupAddView.as_view(), name="coordinategroups_add"),
|
||||
path("coordinate-groups/<int:pk>/", views.CoordinateGroupView.as_view(), name="coordinategroups"),
|
||||
path("coordinate-groups/<int:pk>/edit/", views.CoordinateGroupEditView.as_view(), name="coordinategroups_edit"),
|
||||
path("coordinate-groups/<int:pk>/delete/", views.CoordinateGroupDeleteView.as_view(), name="coordinategroups_delete"),
|
||||
path("coordinate-groups/<int:pk>/changelog/", views.CoordinateGroupChangeLogView.as_view(), name="coordinategroups_changelog", kwargs={'model': models.CoordinateGroups}),
|
||||
|
||||
# Coordinate
|
||||
path("coordinates/", views.CoordinateListView.as_view(), name="coordinates_list"),
|
||||
path("coordinates/add/", views.CoordinateAddView.as_view(), name="coordinates_add"),
|
||||
path("coordinates/<int:pk>/", views.CoordinateView.as_view(), name="coordinates"),
|
||||
path("coordinates/<int:pk>/edit/", views.CoordinateEditView.as_view(), name="coordinates_edit"),
|
||||
path("coordinates/<int:pk>/delete/", views.CoordinateDeleteView.as_view(), name="coordinates_delete"),
|
||||
path("coordinates/<int:pk>/changelog/", views.CoordinateChangeLogView.as_view(), name="coordinates_changelog", kwargs={'model': models.Coordinates}),
|
||||
)
|
||||
|
||||
@@ -29,10 +29,13 @@ from django.shortcuts import render
|
||||
from django.views.generic import View
|
||||
from extras.models import Tag
|
||||
from wireless.models import WirelessLink
|
||||
from netbox.views.generic import ObjectView, ObjectListView, ObjectEditView, ObjectDeleteView, ObjectChangeLogView
|
||||
|
||||
from netbox_topology_views.filters import DeviceFilterSet
|
||||
from netbox_topology_views.forms import DeviceFilterForm, IndividualOptionsForm
|
||||
from netbox_topology_views.models import RoleImage, IndividualOptions
|
||||
|
||||
from netbox_topology_views.filters import DeviceFilterSet, CoordinateFilterSet
|
||||
from netbox_topology_views.forms import DeviceFilterForm, IndividualOptionsForm, CoordinateGroupsForm, CoordinatesForm, CoordinatesFilterForm
|
||||
from netbox_topology_views.models import RoleImage, CoordinateGroups, Coordinates, IndividualOptions
|
||||
from netbox_topology_views.tables import CoordinateGroupListTable, CoordinateListTable
|
||||
from netbox_topology_views.utils import (
|
||||
CONF_IMAGE_DIR,
|
||||
find_image_url,
|
||||
@@ -751,6 +754,80 @@ class TopologyImagesView(PermissionRequiredMixin, View):
|
||||
},
|
||||
)
|
||||
|
||||
class CoordinateView(PermissionRequiredMixin, ObjectView):
|
||||
permission_required = 'netbox_topology_views.view_coordinates'
|
||||
|
||||
queryset = Coordinates.objects.all()
|
||||
|
||||
class CoordinateAddView(PermissionRequiredMixin, ObjectEditView):
|
||||
permission_required = 'netbox_topology_views.add_coordinates'
|
||||
|
||||
queryset = Coordinates.objects.all()
|
||||
form = CoordinatesForm
|
||||
template_name = 'netbox_topology_views/coordinates_add.html'
|
||||
|
||||
class CoordinateListView(PermissionRequiredMixin, ObjectListView):
|
||||
permission_required = 'netbox_topology_views.view_coordinates'
|
||||
|
||||
queryset = Coordinates.objects.all()
|
||||
table = CoordinateListTable
|
||||
template_name = 'netbox_topology_views/coordinates_list.html'
|
||||
filterset = CoordinateFilterSet
|
||||
filterset_form = CoordinatesFilterForm
|
||||
|
||||
class CoordinateEditView(PermissionRequiredMixin, ObjectEditView):
|
||||
permission_required = 'netbox_topology_views.change_coordinates'
|
||||
|
||||
queryset = Coordinates.objects.all()
|
||||
form = CoordinatesForm
|
||||
template_name = 'netbox_topology_views/coordinates_edit.html'
|
||||
|
||||
class CoordinateDeleteView(PermissionRequiredMixin, ObjectDeleteView):
|
||||
permission_required = 'netbox_topology_views.delete_coordinates'
|
||||
|
||||
queryset = Coordinates.objects.all()
|
||||
|
||||
class CoordinateChangeLogView(PermissionRequiredMixin, ObjectChangeLogView):
|
||||
permission_required = 'netbox_topology_views.view_coordinates'
|
||||
|
||||
queryset = Coordinates.objects.all()
|
||||
|
||||
class CoordinateGroupView(PermissionRequiredMixin, ObjectView):
|
||||
permission_required = 'netbox_topology_views.view_coordinategroups'
|
||||
|
||||
queryset = CoordinateGroups.objects.all()
|
||||
|
||||
class CoordinateGroupAddView(PermissionRequiredMixin, ObjectEditView):
|
||||
permission_required = 'netbox_topology_views.add_coordinategroups'
|
||||
|
||||
queryset = CoordinateGroups.objects.all()
|
||||
form = CoordinateGroupsForm
|
||||
template_name = 'netbox_topology_views/coordinategroups_add.html'
|
||||
|
||||
class CoordinateGroupListView(PermissionRequiredMixin, ObjectListView):
|
||||
permission_required = 'netbox_topology_views.view_coordinategroups'
|
||||
|
||||
queryset = CoordinateGroups.objects.all()
|
||||
table = CoordinateGroupListTable
|
||||
template_name = 'netbox_topology_views/coordinategroups_list.html'
|
||||
|
||||
class CoordinateGroupEditView(PermissionRequiredMixin, ObjectEditView):
|
||||
permission_required = 'netbox_topology_views.change_coordinategroups'
|
||||
|
||||
queryset = CoordinateGroups.objects.all()
|
||||
form = CoordinateGroupsForm
|
||||
template_name = 'netbox_topology_views/coordinategroups_edit.html'
|
||||
|
||||
class CoordinateGroupDeleteView(PermissionRequiredMixin, ObjectDeleteView):
|
||||
permission_required = 'netbox_topology_views.delete_coordinategroups'
|
||||
|
||||
queryset = CoordinateGroups.objects.all()
|
||||
|
||||
class CoordinateGroupChangeLogView(PermissionRequiredMixin, ObjectChangeLogView):
|
||||
permission_required = 'netbox_topology_views.view_coordinategroups'
|
||||
|
||||
queryset = CoordinateGroups.objects.all()
|
||||
|
||||
class TopologyIndividualOptionsView(PermissionRequiredMixin, View):
|
||||
permission_required = 'netbox_topology_views.change_individualoptions'
|
||||
|
||||
|
||||
Reference in New Issue
Block a user