add load/save values, fix filterset
This commit is contained in:
@@ -14,7 +14,7 @@ from netbox_topology_views.api.serializers import (
|
||||
RoleImageSerializer,
|
||||
TopologyDummySerializer,
|
||||
)
|
||||
from netbox_topology_views.models import RoleImage, IndividualOptions
|
||||
from netbox_topology_views.models import RoleImage, IndividualOptions, CoordinateGroup, Coordinate
|
||||
from netbox_topology_views.views import get_topology_data
|
||||
from netbox_topology_views.utils import get_image_from_url, export_data_to_xml, get_query_settings
|
||||
from netbox_topology_views.filters import DeviceFilterSet
|
||||
@@ -50,6 +50,8 @@ class SaveCoordsViewSet(ReadOnlyModelViewSet):
|
||||
if not actual_device:
|
||||
return Response({"status": "invalid node_id in body"}, status=400)
|
||||
|
||||
# Storing coordinates in custom field is deprecated now.
|
||||
# We preserve this for backwards compatibility.
|
||||
try:
|
||||
actual_device.custom_field_data["coordinates"] = "%s;%s" % (
|
||||
x_coord,
|
||||
@@ -61,6 +63,40 @@ class SaveCoordsViewSet(ReadOnlyModelViewSet):
|
||||
{"status": "coords custom field could not be saved"}, status=500
|
||||
)
|
||||
|
||||
# Default group named "default" must always exist in order to make sure
|
||||
# that coordinate values can be stored even if no coordinate group has been
|
||||
# selected. The default group will be added automatically if it does not exist.
|
||||
try:
|
||||
group = CoordinateGroup.objects.get(name="default")
|
||||
except CoordinateGroup.DoesNotExist:
|
||||
try:
|
||||
group = CoordinateGroup(
|
||||
name="default",
|
||||
description="Automatically generated default group. If you delete "
|
||||
"this group, all default coordinates are gone for good but "
|
||||
"the group itself will be re-created."
|
||||
)
|
||||
group.save()
|
||||
except:
|
||||
return Response(
|
||||
{"status": "Error while creating default group."}, status=500
|
||||
)
|
||||
|
||||
try:
|
||||
# Hen-and-egg-problem. Thanks, Django! By default, Django updates records that
|
||||
# already exist and inserts otherwise. This does not work with our
|
||||
# unique_together key if no pk is given. But: No record, no pk.
|
||||
if not Coordinate.objects.filter(group=group, device=actual_device):
|
||||
# Unique group/device pair does not exist. Prepare new data set
|
||||
coords = Coordinate(group=group, device=actual_device, x=x_coord, y=y_coord)
|
||||
else:
|
||||
# Unique group/device pair already exists. Update data
|
||||
coords = Coordinate(pk=Coordinate.objects.get(group=group, device=actual_device).pk, group=group, device=actual_device, x=x_coord, y=y_coord)
|
||||
coords.save()
|
||||
except:
|
||||
return Response(
|
||||
{"status": "Coordinates could not be saved."}, status=500
|
||||
)
|
||||
return Response({"status": "saved coords"})
|
||||
|
||||
class ExportTopoToXML(PermissionRequiredMixin, ViewSet):
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import django_filters
|
||||
from dcim.choices import DeviceStatusChoices
|
||||
from dcim.models import Device, DeviceRole, Location, Rack, Region, Site
|
||||
from .models import Coordinate
|
||||
from .models import Coordinate, CoordinateGroup
|
||||
from django.db.models import Q
|
||||
from netbox.filtersets import NetBoxModelFilterSet
|
||||
from tenancy.filtersets import TenancyFilterSet
|
||||
@@ -55,14 +55,24 @@ class DeviceFilterSet(TenancyFilterSet, NetBoxModelFilterSet):
|
||||
qs_filter = Q(name__icontains=value)
|
||||
return queryset.filter(qs_filter)
|
||||
|
||||
class CoordinateFilterSet(NetBoxModelFilterSet):
|
||||
class CoordinatesFilterSet(NetBoxModelFilterSet):
|
||||
group = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset = CoordinateGroup.objects.all(),
|
||||
)
|
||||
|
||||
device = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset = Device.objects.all(),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = Coordinate
|
||||
fields = ('id', 'group', 'device', 'x', 'y')
|
||||
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)
|
||||
return queryset.filter(
|
||||
Q(group__name__icontains=value) |
|
||||
Q(device__name__icontains=value)
|
||||
)
|
||||
@@ -162,27 +162,21 @@ class CoordinatesForm(NetBoxModelForm):
|
||||
|
||||
class CoordinatesFilterForm(NetBoxModelFilterSetForm):
|
||||
model = Coordinate
|
||||
fieldsets = (
|
||||
(None, ('q', 'filter_id')),
|
||||
('Coordinates', ('group', 'device', 'x', 'y'))
|
||||
)
|
||||
|
||||
group = forms.ModelMultipleChoiceField(
|
||||
queryset=CoordinateGroup.objects.all(),
|
||||
required=False
|
||||
)
|
||||
|
||||
device = DynamicModelChoiceField(
|
||||
device = DynamicModelMultipleChoiceField(
|
||||
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
|
||||
)
|
||||
|
||||
@@ -121,7 +121,7 @@ class CoordinateGroup(NetBoxModel):
|
||||
|
||||
class Coordinate(NetBoxModel):
|
||||
"""
|
||||
Coordinates are being used to place devices in a topology view onto a certian
|
||||
Coordinates are being used to place devices in a topology view onto a certain
|
||||
position. Devices belong to one or more coordinate groups. They have to
|
||||
be unique together.
|
||||
"""
|
||||
@@ -147,11 +147,6 @@ class Coordinate(NetBoxModel):
|
||||
def get_absolute_url(self):
|
||||
return reverse('plugins:netbox_topology_views:coordinate', 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'),
|
||||
|
||||
@@ -32,7 +32,7 @@ from wireless.models import WirelessLink
|
||||
from netbox.views.generic import ObjectView, ObjectListView, ObjectEditView, ObjectDeleteView, ObjectChangeLogView
|
||||
|
||||
|
||||
from netbox_topology_views.filters import DeviceFilterSet, CoordinateFilterSet
|
||||
from netbox_topology_views.filters import DeviceFilterSet, CoordinatesFilterSet
|
||||
from netbox_topology_views.forms import DeviceFilterForm, IndividualOptionsForm, CoordinateGroupsForm, CoordinatesForm, CoordinatesFilterForm
|
||||
from netbox_topology_views.models import RoleImage, CoordinateGroup, Coordinate, IndividualOptions
|
||||
from netbox_topology_views.tables import CoordinateGroupListTable, CoordinateListTable
|
||||
@@ -156,8 +156,31 @@ def create_node(
|
||||
node["href"] = device.get_absolute_url()
|
||||
node["image"] = get_image_for_entity(device)
|
||||
|
||||
# Default group named "default" must always exist in order to make sure
|
||||
# that coordinate values can be stored even if no coordinate group has been
|
||||
# selected. The default group will be added automatically if it does not exist.
|
||||
try:
|
||||
group = CoordinateGroup.objects.get(name="default")
|
||||
except CoordinateGroup.DoesNotExist:
|
||||
try:
|
||||
group = CoordinateGroup(
|
||||
name="default",
|
||||
description="Automatically generated default group. If you delete "
|
||||
"this group, all default coordinates are gone for good but "
|
||||
"the group itself will be re-created."
|
||||
)
|
||||
group.save()
|
||||
except:
|
||||
pass
|
||||
|
||||
node["physics"] = True
|
||||
if "coordinates" in device.custom_field_data:
|
||||
if Coordinate.objects.filter(group=group, device=device.pk).values('x') and Coordinate.objects.filter(group=group, device=device.pk).values('y'):
|
||||
node["x"] = Coordinate.objects.get(group=group, device=device.pk).x
|
||||
node["y"] = Coordinate.objects.get(group=group, device=device.pk).y
|
||||
node["physics"] = False
|
||||
elif "coordinates" in device.custom_field_data:
|
||||
# We prefer the new Coordinate model but leave the deprecated method
|
||||
# for now as fallback for compatibility reasons
|
||||
if device.custom_field_data["coordinates"] is not None:
|
||||
if ";" in device.custom_field_data["coordinates"]:
|
||||
cords = device.custom_field_data["coordinates"].split(";")
|
||||
@@ -166,6 +189,9 @@ def create_node(
|
||||
node["physics"] = False
|
||||
elif save_coords:
|
||||
node["physics"] = False
|
||||
elif save_coords:
|
||||
node["physics"] = False
|
||||
|
||||
return node
|
||||
|
||||
|
||||
@@ -772,7 +798,7 @@ class CoordinateListView(PermissionRequiredMixin, ObjectListView):
|
||||
queryset = Coordinate.objects.all()
|
||||
table = CoordinateListTable
|
||||
template_name = 'netbox_topology_views/coordinate_list.html'
|
||||
filterset = CoordinateFilterSet
|
||||
filterset = CoordinatesFilterSet
|
||||
filterset_form = CoordinatesFilterForm
|
||||
|
||||
class CoordinateEditView(PermissionRequiredMixin, ObjectEditView):
|
||||
|
||||
Reference in New Issue
Block a user