Node API Reference¶
Complete reference for all methods available on Node model instances and the Node manager. For practical examples and usage patterns, see Filtering Graph Traversals and Working with Paths and Algorithms.
Many of the examples on this page use the graph from the Quickstart:
flowchart TD
root --> a1 & a2 & a3
a1 --> b1 & b2
a2 --> b2
a3 --> b3 & b4
b3 --> c1 & c2
b4 --> c1
Manager Methods¶
These are called on MyNode.objects.
- roots(self, node=None)
Returns a QuerySet of all root nodes (nodes with no parents). If
nodeis provided, returns only the roots reachable from that node.- leaves(self, node=None)
Returns a QuerySet of all leaf nodes (nodes with no children). If
nodeis provided, returns only the leaves reachable from that node.- connected_components(self)
Returns a list of QuerySets, one per disconnected subgraph. Each QuerySet can be further filtered.
Each returned QuerySet is a disconnected subgraph. Nodes with no edges (islands) form their own component:
flowchart TD
subgraph Component 1
root --> a1 & a2 & a3
a1 --> b1
a2 --> b1
a3 --> b2
end
subgraph Component 2
island
end
- graph_stats(self)
Returns a dict with aggregate metrics:
node_count,edge_count,root_count,leaf_count,island_count,max_depth,avg_depth,density,component_count. Runs O(N) queries - suitable for analytics, not hot paths.- topological_sort(self, max_depth=None)
Returns a QuerySet of all nodes in topological order (parents before children). Island nodes are included at the front.
Topological order places every parent before its children. Nodes at the same depth appear in the same tier:
flowchart LR
subgraph "depth 0"
root
end
subgraph "depth 1"
a1
a2
a3
end
subgraph "depth 2"
b1
b2
b3
b4
end
subgraph "depth 3"
c1
c2
end
root --> a1 & a2 & a3
a1 --> b1 & b2
a2 --> b2
a3 --> b3 & b4
b3 --> c1 & c2
b4 --> c1
- critical_path(self, weight_field=None, max_depth=None)
Returns a
(QuerySet, total_weight)tuple for the longest weighted path from any root to any leaf. Withoutweight_field, uses hop count (each edge = 1).
The critical path (green) is the longest path from any root to any leaf. With uniform edge weights of 1, this is root - a3 - b3 - c1 (total weight: 3):
flowchart TD
root ==> a3
root --> a1 & a2
a1 --> b1 & b2
a2 --> b2
a3 ==> b3
a3 --> b4
b3 ==> c1
b3 --> c2
b4 --> c1
style root fill:#4CAF50,color:#fff
style a3 fill:#4CAF50,color:#fff
style b3 fill:#4CAF50,color:#fff
style c1 fill:#4CAF50,color:#fff
- transitive_reduction(self, delete=False)
Identifies redundant edges (A→C is redundant if C is reachable from A via a path of length >= 2). Returns a QuerySet of redundant edges by default (dry run). With
delete=True, deletes them and returns the count.
An edge is redundant if the child is already reachable through a longer path. Here, A - C (dashed red) is redundant because C is reachable from A via B. transitive_reduction() identifies and optionally deletes these edges:
flowchart TD
A --> B --> C
A -.->|redundant| C
linkStyle 2 stroke:#F44336,stroke-width:2px
After reduction, reachability is unchanged but the redundant shortcut is removed:
flowchart TD
A --> B --> C
Mutation Methods¶
- add_child(self, child, **kwargs)
Creates an edge from this node to
child. Extra keyword arguments are passed to the edge model constructor. Supports special kwargs:disable_circular_check(defaultFalse),allow_duplicate_edges(defaultTrue),allow_redundant_edges(default from setting orTrue). See Configuration Reference for details.- remove_child(self, child, delete_node=False)
Removes the edge to
child. IfchildisNone, removes edges to all children. Withdelete_node=True, also deletes the child node(s).- add_parent(self, parent, *args, **kwargs)
Creates an edge from
parentto this node. Accepts the same special kwargs asadd_child().- remove_parent(self, parent, delete_node=False)
Removes the edge from
parent. IfparentisNone, removes edges from all parents. Withdelete_node=True, also deletes the parent node(s).
Traversal Methods¶
All traversal methods accept optional keyword arguments for filtering: max_depth, edge_type, disallowed_edges_queryset, allowed_edges_queryset, disallowed_nodes_queryset, allowed_nodes_queryset, limiting_edges_set_fk.
b3.ancestors() returns all nodes reachable by following edges upward (green). The starting node (orange) is not included:
flowchart TD
root --> a1 & a2 & a3
a1 --> b1 & b2
a2 --> b2
a3 --> b3 & b4
b3 --> c1 & c2
b4 --> c1
style root fill:#4CAF50,color:#fff
style a3 fill:#4CAF50,color:#fff
style b3 fill:#FF9800,color:#fff
a3.descendants() returns all nodes reachable by following edges downward (green):
flowchart TD
root --> a1 & a2 & a3
a1 --> b1 & b2
a2 --> b2
a3 --> b3 & b4
b3 --> c1 & c2
b4 --> c1
style a3 fill:#FF9800,color:#fff
style b3 fill:#4CAF50,color:#fff
style b4 fill:#4CAF50,color:#fff
style c1 fill:#4CAF50,color:#fff
style c2 fill:#4CAF50,color:#fff
- ancestors(self, **kwargs)
Returns a QuerySet of all nodes reachable by following edges toward roots.
- ancestors_count(self)
Returns the total number of ancestor nodes.
- self_and_ancestors(self, **kwargs)
Returns a list starting with self, followed by ancestors.
- ancestors_and_self(self, **kwargs)
Returns a QuerySet of ancestors with self appended.
- descendants(self, **kwargs)
Returns a QuerySet of all nodes reachable by following edges toward leaves.
- descendants_count(self)
Returns the total number of descendant nodes.
- self_and_descendants(self, **kwargs)
Returns a QuerySet starting with self, followed by descendants.
- descendants_and_self(self, **kwargs)
Returns a list of descendants ordered from furthest (leaves) to nearest, with self appended at the end. Mirrors the ordering of
ancestors_and_self()(furthest-first, converging toward self).- clan(self, **kwargs)
Returns a QuerySet of all ancestors, self, and all descendants.
b3.clan() returns ancestors (green), self (orange), and descendants (green) - the complete vertical slice through b3:
flowchart TD
root --> a1 & a2 & a3
a1 --> b1 & b2
a2 --> b2
a3 --> b3 & b4
b3 --> c1 & c2
b4 --> c1
style root fill:#4CAF50,color:#fff
style a3 fill:#4CAF50,color:#fff
style b3 fill:#FF9800,color:#fff
style c1 fill:#4CAF50,color:#fff
style c2 fill:#4CAF50,color:#fff
- clan_count(self)
Returns the total number of clan nodes.
- siblings(self)
Returns a QuerySet of nodes that share a parent with this node, excluding self.
a1.siblings() returns nodes that share a parent with a1 (green). Since root is parent of a1, a2, and a3, the siblings are a2 and a3:
flowchart TD
root --> a1 & a2 & a3
style a1 fill:#FF9800,color:#fff
style a2 fill:#4CAF50,color:#fff
style a3 fill:#4CAF50,color:#fff
- siblings_count(self)
Returns the count of sibling nodes.
- siblings_with_self(self)
Returns a QuerySet of siblings including self.
- partners(self)
Returns a QuerySet of nodes that share a child with this node, excluding self.
a1.partners() returns nodes that share a child with a1 (green). Both a1 and a2 are parents of b2, so a2 is a partner:
flowchart TD
a1 --> b2
a2 --> b2
style a1 fill:#FF9800,color:#fff
style a2 fill:#4CAF50,color:#fff
- partners_count(self)
Returns the count of partner nodes.
- partners_with_self(self)
Returns a QuerySet of partners including self.
- connected_graph(self, **kwargs)
Returns a QuerySet of all nodes connected in any direction to this node. Supports all filter kwargs including
max_depth,disallowed_nodes_queryset,allowed_nodes_queryset,disallowed_edges_queryset,allowed_edges_queryset, andlimiting_edges_set_fk.- connected_graph_node_count(self, **kwargs)
Returns the count of nodes in the connected graph.
Path Methods¶
- path(self, ending_node, **kwargs)
Returns a QuerySet of the shortest path from self to
ending_node. Sorted root-side toward leaf-side regardless of direction. RaisesNodeNotReachableExceptionif no path exists. Acceptsdirectional(defaultTrue) - set toFalseto search in both directions.
root.path(c1) returns the shortest path (green). Here, root - a3 - b3 - c1 and root - a3 - b4 - c1 are both 3 hops; path() returns one:
flowchart TD
root ==> a3
root --> a1 & a2
a1 --> b1 & b2
a2 --> b2
a3 ==> b3
a3 --> b4
b3 ==> c1
b3 --> c2
b4 --> c1
style root fill:#4CAF50,color:#fff
style a3 fill:#4CAF50,color:#fff
style b3 fill:#4CAF50,color:#fff
style c1 fill:#4CAF50,color:#fff
- path_exists(self, ending_node, **kwargs)
Returns
Trueif a path exists from self toending_node. Acceptsdirectional.- distance(self, ending_node, **kwargs)
Returns the shortest hop count to
ending_node.- all_paths(self, ending_node, directional=True, max_results=None, **kwargs)
Returns a list of QuerySets, each representing one path. Unlike
path(), returns all paths, not just the shortest.
root.all_paths(c1) returns both paths: root - a3 - b3 - c1 (green) and root - a3 - b4 - c1 (blue):
flowchart TD
root --> a1 & a2 & a3
a1 --> b1 & b2
a2 --> b2
a3 --> b3 & b4
b3 --> c1 & c2
b4 --> c1
linkStyle 2 stroke:#4CAF50,stroke-width:3px
linkStyle 6 stroke:#4CAF50,stroke-width:3px
linkStyle 8 stroke:#4CAF50,stroke-width:3px
linkStyle 7 stroke:#2196F3,stroke-width:3px
linkStyle 10 stroke:#2196F3,stroke-width:3px
- all_paths_as_pk_lists(self, ending_node, directional=True, max_results=None, **kwargs)
Returns a list of PK lists - lightweight alternative to
all_paths().- weighted_path(self, ending_node, weight_field=“weight”, **kwargs)
Returns a
(QuerySet, total_weight)tuple for the minimum-weight path. The edge model must have the specified weight field. RaisesNodeNotReachableExceptionorWeightFieldDoesNotExistException.- weighted_path_raw(self, ending_node, weight_field=“weight”, directional=True, **kwargs)
Returns a
WeightedPathResult(nodes, total_weight)namedtuple with raw PK list.- weighted_distance(self, ending_node, weight_field=“weight”, **kwargs)
Returns the total weight of the minimum-weight path.
Predicate Methods¶
- is_root(self)
Returns
Trueif this node has children but no parents.- is_leaf(self)
Returns
Trueif this node has parents but no children.- is_island(self)
Returns
Trueif this node has no parents and no children.- is_ancestor_of(self, ending_node, **kwargs)
Returns
Trueif self is an ancestor ofending_node. Acceptsdirectional.- is_descendant_of(self, ending_node, **kwargs)
Returns
Trueif self is a descendant ofending_node. Acceptsdirectional.- is_sibling_of(self, ending_node)
Returns
Trueif self andending_nodeshare a parent.- is_partner_of(self, ending_node)
Returns
Trueif self andending_nodeshare a child.
Tree Methods¶
- descendants_tree(self)
Returns a nested dict representing the descendant tree. Each key is a node, each value is a dict of that node’s children.
a3.descendants_tree() returns a nested dict mirroring this subgraph. Each node maps to a dict of its children:
flowchart TD
a3 --> b3 & b4
b3 --> c1 & c2
b4 --> c1
style a3 fill:#FF9800,color:#fff
- ancestors_tree(self)
Returns a nested dict representing the ancestor tree. Each key is a node, each value is a dict of that node’s parents.
Edge Query Methods¶
- descendants_edges(self)
Returns a QuerySet of descendant edges, topologically sorted from root-side to leaf-side.
- ancestors_edges(self)
Returns a QuerySet of ancestor edges, topologically sorted from root-side to leaf-side.
- clan_edges(self)
Returns a QuerySet of all edges associated with this node.
Root and Leaf Methods¶
- roots(self)
Returns a set of all root nodes reachable from this node.
- leaves(self)
Returns a set of all leaf nodes reachable from this node.
Depth and Topological Methods¶
- node_depth(self)
Returns the longest path distance from any root to this node. Returns 0 for root and island nodes.
Depth is the longest path distance from any root to a node. Roots have depth 0:
flowchart TD
root["root (depth 0)"] --> a1["a1 (depth 1)"] & a2["a2 (depth 1)"] & a3["a3 (depth 1)"]
a1 --> b1["b1 (depth 2)"] & b2["b2 (depth 2)"]
a2 --> b2
a3 --> b3["b3 (depth 2)"] & b4["b4 (depth 2)"]
b3 --> c1["c1 (depth 3)"] & c2["c2 (depth 3)"]
b4 --> c1
- ancestors_with_depth(self, **kwargs)
Returns a list of
(ancestor_node, depth)tuples, where depth is the longest path distance from the ancestor to this node. Supports filter kwargs:disallowed_nodes_queryset,allowed_nodes_queryset,disallowed_edges_queryset,allowed_edges_queryset,limiting_edges_set_fk.- descendants_with_depth(self, **kwargs)
Returns a list of
(descendant_node, depth)tuples, where depth is the longest path distance from this node to the descendant. Supports the same filter kwargs asancestors_with_depth().- topological_descendants(self, **kwargs)
Returns a QuerySet of self followed by all descendants in topological order.
Lowest Common Ancestor¶
- lowest_common_ancestors(self, other, **kwargs)
Returns a QuerySet of the lowest common ancestor(s) between this node and
other. DAGs can have multiple LCAs. Returns empty QuerySet if nodes are disconnected.
b1.lowest_common_ancestors(b3) returns root (orange) - the deepest node that is an ancestor of both b1 and b3 (blue):
flowchart TD
root --> a1 & a2 & a3
a1 --> b1 & b2
a2 --> b2
a3 --> b3 & b4
b3 --> c1 & c2
b4 --> c1
style b1 fill:#2196F3,color:#fff
style b3 fill:#2196F3,color:#fff
style root fill:#FF9800,color:#fff
Unlike trees, DAGs can have multiple LCAs. Here, m and n (blue) share two LCAs: p1 and p2 (orange), because neither is an ancestor of the other:
flowchart TD
p1 --> m & n
p2 --> m & n
style m fill:#2196F3,color:#fff
style n fill:#2196F3,color:#fff
style p1 fill:#FF9800,color:#fff
style p2 fill:#FF9800,color:#fff
Graph Hashing¶
Requires NetworkX. See Exporting and Transforming Graphs for background.
- graph_hash(self, scope=“connected”, **kwargs)
Returns a Weisfeiler-Lehman graph hash string. Scope options:
"connected","descendants","ancestors","clan".- subgraph_hashes(self, scope=“connected”, **kwargs)
Returns a dict of
{node_pk: [hash_str, ...]}for WL subgraph hashes. Requires NetworkX >= 3.3.