Quellcode durchsuchen

Add origins, destinations properties on CablePath

jeremystretch vor 3 Jahren
Ursprung
Commit
6ff2e55ce4

+ 1 - 1
netbox/dcim/api/serializers.py

@@ -1078,7 +1078,7 @@ class CablePathSerializer(serializers.ModelSerializer):
     @swagger_serializer_method(serializer_or_field=serializers.ListField)
     def get_path(self, obj):
         ret = []
-        for node in obj.get_path():
+        for node in obj.path_objects():
             serializer = get_serializer_for_model(node, prefix='Nested')
             context = {'request': self.context['request']}
             ret.append(serializer(node, context=context).data)

+ 49 - 23
netbox/dcim/models/cables.py

@@ -324,11 +324,55 @@ class CablePath(models.Model):
         super().save(*args, **kwargs)
 
         # Record a direct reference to this CablePath on its originating object(s)
-        origins = [path_node_to_object(n) for n in self.path[0]]
-        origin_model = origins[0]._meta.model
-        origin_ids = [o.id for o in origins]
+        origin_model = self.origins[0]._meta.model
+        origin_ids = [o.id for o in self.origins]
         origin_model.objects.filter(pk__in=origin_ids).update(_path=self.pk)
 
+    @property
+    def origin_type(self):
+        ct_id, _ = decompile_path_node(self.path[0][0])
+        return ContentType.objects.get_for_id(ct_id)
+
+    @property
+    def destination_type(self):
+        if not self.is_complete:
+            return None
+        ct_id, _ = decompile_path_node(self.path[-1][0])
+        return ContentType.objects.get_for_id(ct_id)
+
+    @property
+    def path_objects(self):
+        """
+        Cache and return the complete path as lists of objects, derived from their annotation within the path.
+        """
+        if not hasattr(self, '_path_objects'):
+            self._path_objects = self._get_path()
+        return self._path_objects
+
+    @property
+    def origins(self):
+        """
+        Return the list of originating objects (from cache, if available).
+        """
+        if hasattr(self, '_path_objects'):
+            return self.path_objects[0]
+        return [
+            path_node_to_object(node) for node in self.path[0]
+        ]
+
+    @property
+    def destinations(self):
+        """
+        Return the list of destination objects (from cache, if available), if the path is complete.
+        """
+        if not self.is_complete:
+            return []
+        if hasattr(self, '_path_objects'):
+            return self.path_objects[-1]
+        return [
+            path_node_to_object(node) for node in self.path[-1]
+        ]
+
     @property
     def segment_count(self):
         return int(len(self.path) / 3)
@@ -474,9 +518,7 @@ class CablePath(models.Model):
         """
         Retrace the path from the currently-defined originating termination(s)
         """
-        _new = self.from_origin([
-            path_node_to_object(node) for node in self.path[0]
-        ])
+        _new = self.from_origin(self.origins)
         if _new:
             self.path = _new.path
             self.is_complete = _new.is_complete
@@ -486,7 +528,7 @@ class CablePath(models.Model):
         else:
             self.delete()
 
-    def get_path(self):
+    def _get_path(self):
         """
         Return the path as a list of prefetched objects.
         """
@@ -518,22 +560,6 @@ class CablePath(models.Model):
 
         return path
 
-    def get_destination(self):
-        if not self.is_complete:
-            return None
-        return [
-            path_node_to_object(node) for node in self.path[-1]
-        ]
-
-    @property
-    def last_nodes(self):
-        """
-        Return either the destination or the last node within the path.
-        """
-        return [
-            path_node_to_object(node) for node in self.path[-1]
-        ]
-
     def get_cable_ids(self):
         """
         Return all Cable IDs within the path.

+ 2 - 2
netbox/dcim/models/device_components.py

@@ -200,7 +200,7 @@ class PathEndpoint(models.Model):
             if origin._path is None:
                 break
 
-            path.extend(*origin._path.get_path())
+            path.extend(origin._path.path_objects)
             while (len(path)) % 3:
                 # Pad to ensure we have complete three-tuples (e.g. for paths that end at a non-connected FrontPort)
                 # by inserting empty entries immediately prior to the path's destination node(s)
@@ -231,7 +231,7 @@ class PathEndpoint(models.Model):
         Caching accessor for the attached CablePath's destination (if any)
         """
         if not hasattr(self, '_connected_endpoints'):
-            self._connected_endpoints = self._path.get_destination() if self._path else []
+            self._connected_endpoints = self._path.destinations if self._path else []
         return self._connected_endpoints
 
 

+ 1 - 2
netbox/dcim/utils.py

@@ -64,5 +64,4 @@ def rebuild_paths(terminations):
         with transaction.atomic():
             for cp in cable_paths:
                 cp.delete()
-                origins = [path_node_to_object(node) for node in cp.path[0]]
-                create_cablepath(origins)
+                create_cablepath(cp.origins)