Edge API Reference¶
Complete reference for all methods available on the Edge manager. For practical examples, see Filtering Graph Traversals and Working with Paths and Algorithms.
Manager Methods¶
These are called on MyEdge.objects.
- from_nodes_queryset(self, nodes_queryset)
Given a QuerySet of nodes, returns a QuerySet of all edges where both parent and child are in the provided nodes.
Given a queryset containing root, a1, a2, b1, and b2 (green), from_nodes_queryset() returns only the solid edges - those where both parent and child are in the queryset. Dashed edges are excluded:
flowchart TD
root --> a1 & a2
root -.-> a3
a1 --> b1 & b2
a2 --> b2
a3 -.-> b3 & b4
b3 -.-> c1 & c2
b4 -.-> c1
style root fill:#4CAF50,color:#fff
style a1 fill:#4CAF50,color:#fff
style a2 fill:#4CAF50,color:#fff
style b1 fill:#4CAF50,color:#fff
style b2 fill:#4CAF50,color:#fff
- descendants(self, node, **kwargs)
Returns a QuerySet of all edges descended from the given node.
- ancestors(self, node, **kwargs)
Returns a QuerySet of all edges which are ancestors of the given node.
MyEdge.objects.ancestors(b3) returns the edges (green) on paths from b3 upward toward roots:
flowchart TD
root -->|returned| a3
a3 -->|returned| b3
b3 --> c1 & c2
b4 --> c1
linkStyle 0 stroke:#4CAF50,stroke-width:3px
linkStyle 1 stroke:#4CAF50,stroke-width:3px
- clan(self, node, **kwargs)
Returns a QuerySet of all edges for ancestors, self, and descendants of the given node.
- path(self, start_node, end_node, **kwargs)
Returns a QuerySet of edges forming the shortest path from
start_nodetoend_node. Acceptsdirectional(defaultTrue).- redundant_edges(self)
Returns a QuerySet of redundant edges - those removable by transitive reduction. An edge A→C is redundant if C is reachable from A via a path of length >= 2.
An edge A - C is redundant if C is reachable from A through a longer path. redundant_edges() returns these edges; transitive_reduction(delete=True) removes them:
flowchart TD
A --> B --> C
A -.->|redundant| C
linkStyle 2 stroke:#F44336,stroke-width:2px
- transitive_reduction(self, delete=False)
Identifies redundant edges. With
delete=True, removes them and returns the count. See alsoNodeManager.transitive_reduction().- validate_route(self, edges, **kwargs)
Given an ordered list of edge instances, returns
Trueif they form a contiguous route (each edge’s child matches the next edge’s parent). A single edge or empty list is always valid.- sort(self, edges, **kwargs)
Given a list or set of edge instances, sorts them from root-side to leaf-side using
node_depth().
Inserting a Node into an Edge¶
insert_node(self, edge, node, clone_to_rootside=False, clone_to_leafside=False, pre_save=None, post_save=None)
Inserts a node into an existing edge, splitting it into two new edges. Returns a tuple of (rootside_edge, leafside_edge).
The process:
Creates a new edge from the original edge’s parent to the inserted node
Creates a new edge from the inserted node to the original edge’s child
Deletes the original edge
After deletion, the original edge instance still exists in memory but not in the database. Run del edge_instance to clean up.
Cloning edge properties¶
clone_to_rootside=True copies the original edge’s field values to the new parent-to-inserted-node edge. clone_to_leafside=True does the same for the inserted-node-to-child edge.
Cloning fails if a field has unique=True. Use pre_save to clear or modify unique fields before saving:
def pre_save(new_edge):
new_edge.name = ""
return new_edge
A post_save function can be used to rebuild relationships after the new edges are created.
Example¶
Insert node n2 into the edge between n1 and n3, cloning the original edge’s properties to the rootside edge:
Inserting n2 (green) into the edge between n1 and n3 splits it into two new edges:
Before:
flowchart TD
n1 -->|original edge| n3
After:
flowchart TD
n1 -->|rootside edge| n2
n2 -->|leafside edge| n3
style n2 fill:#4CAF50,color:#fff
from myapp.models import NetworkEdge, NetworkNode
n1 = NetworkNode.objects.create(name="n1")
n2 = NetworkNode.objects.create(name="n2")
n3 = NetworkNode.objects.create(name="n3")
# Connect n3 to n1
n1.add_child(n3)
e1 = NetworkEdge.objects.last()
# Clear the auto-generated `name` field (it's unique)
def pre_save(new_edge):
new_edge.name = ""
return new_edge
NetworkEdge.objects.insert_node(e1, n2, clone_to_rootside=True, pre_save=pre_save)