Methods on Node and Edge¶
Listed below are the methods that are useful for building/manipulating/querying the graph. We ignore here the methods used only for internal functionality.
Node¶
Manager Methods¶
roots(self, node=None)
Returns a Queryset of all root nodes (nodes with no parents) in the Node model. If a node instance is specified, returns only the roots for that node.
leaves(self, node=None)
Returns a Queryset of all leaf nodes (nodes with no children) in the Node model. If a node instance is specified, returns only the leaves for that node.
Model Methods¶
Methods used for building/manipulating¶
add_child(self, child, **kwargs)
Provided with a Node instance, attaches that instance as a child to the current Node instance
remove_child(self, child, delete_node=False)
Removes the edge connecting this node to child if a child Node instance is provided, otherwise removes the edges connecting to all children. Optionally deletes the child(ren) node(s) as well.
add_parent(self, parent, \*args, **kwargs)
Provided with a Node instance, attaches the current instance as a child to the provided Node instance
remove_parent(self, parent, delete_node=False)
Removes the edge connecting this node to parent if a parent Node instance is provided, otherwise removes the edges connecting to all parents. Optionally deletes the parent node(s) as well.
Methods used for querying¶
ancestors(self, **kwargs)
Returns a QuerySet of all nodes in connected paths in a rootward direction
ancestors_count(self)
Returns an integer number representing the total number of ancestor nodes
self_and_ancestors(self, **kwargs)
Returns a QuerySet of all nodes in connected paths in a rootward direction, prepending with self
ancestors_and_self(self, **kwargs)
Returns a QuerySet of all nodes in connected paths in a rootward direction, appending with self
descendants(self, **kwargs)
Returns a QuerySet of all nodes in connected paths in a leafward direction
descendants_count(self)
Returns an integer number representing the total number of descendant nodes
self_and_descendants(self, **kwargs)
Returns a QuerySet of all nodes in connected paths in a leafward direction, prepending with self
descendants_and_self(self, **kwargs)
Returns a QuerySet of all nodes in connected paths in a leafward direction, appending with self
clan(self, **kwargs)
Returns a QuerySet with all ancestors nodes, self, and all descendant nodes
clan_count(self)
Returns an integer number representing the total number of clan nodes
siblings(self)
Returns a QuerySet of all nodes that share a parent with this node, excluding self
siblings_count(self)
Returns count of all nodes that share a parent with this node
siblings_with_self(self)
Returns a QuerySet of all nodes that share a parent with this node and self
partners(self)
Returns a QuerySet of all nodes that share a child with this node, excluding self
partners_count(self)
Returns count of all nodes that share a child with this node
partners_with_self(self)
Returns a QuerySet of all nodes that share a child with this node and self
path_exists(self, ending_node, **kwargs)
Given an ending Node instance, returns a boolean value determining whether there is a path from the current Node instance to the ending Node instance
Optional keyword argument: directional (boolean: if True, path searching operates normally, in a leafward only direction. If False, search operates in both directions)
path(self, ending_node, **kwargs)
Returns a QuerySet of the shortest path from self to ending node, optionally in either direction. The resulting Queryset is sorted from root-side, toward leaf-side, regardless of the relative position of starting and ending nodes.
Optional keyword argument: directional (boolean: if True, path searching operates normally, in a leafward only direction. If False, search operates in both directions)
distance(self, ending_node, **kwargs)
Returns the shortest hops count to the target node
is_root(self)
Returns True if the current Node instance has children, but no parents
is_leaf(self)
Returns True if the current Node instance has parents, but no children
is_island(self)
Returns True if the current Node instance has no parents nor children
is_ancestor_of(self, ending_node, **kwargs)
Provided an ending_node Node instance, returns True if the current Node instance and is an ancestor of the provided Node instance
Optional keyword argument: directional (boolean: if True, path searching operates normally, in a leafward only direction. If False, search operates in both directions)
is_descendant_of(self, ending_node, **kwargs)
Provided an ending_node Node instance, returns True if the current Node instance and is a descendant of the provided Node instance
Optional keyword argument: directional (boolean: if True, path searching operates normally, in a leafward only direction. If False, search operates in both directions)
is_sibling_of(self, ending_node)
Provided an ending_node Node instance, returns True if the provided Node instance and the current Node instance share a parent Node
is_partner_of(self, ending_node)
Provided an ending_node Node instance, returns True if the provided Node instance and the current Node instance share a child Node
node_depth(self)
Returns an integer representing the depth of this Node instance from furthest root
Not yet implemented
connected_graph(self, **kwargs)
Returns a QuerySet of all nodes connected in any way to the current Node instance
connected_graph_node_count(self, **kwargs)
Returns the number of nodes in the graph connected in any way to the current Node instance
descendants_tree(self)
Returns a tree-like structure with descendants for the current Node
ancestors_tree(self)
Returns a tree-like structure with ancestors for the current Node
roots(self)
Returns a QuerySet of all root nodes, if any, for the current Node
leaves(self)
Returns a QuerySet of all leaf nodes, if any, for the current Node
descendants_edges(self)
Returns a QuerySet of descendant Edge instances for the current Node
ancestors_edges(self)
Returns a QuerySet of ancestor Edge instances for the current Node
clan_edges(self)
Returns a QuerySet of all Edge instances associated with a given node
Edge¶
Manager Methods¶
from_nodes_queryset(self, nodes_queryset)
Provided a QuerySet of nodes, returns a QuerySet of all Edge instances where a parent and child Node are within the QuerySet of nodes
descendants(self, node, **kwargs)
Returns a QuerySet of all Edge instances descended from the given Node instance
ancestors(self, node, **kwargs)
Returns a QuerySet of all Edge instances which are ancestors of the given Node instance
clan(self, node, **kwargs)
Returns a QuerySet of all Edge instances for ancestors, self, and descendants
path(self, start_node, end_node, **kwargs)
Returns a QuerySet of all Edge instances for the shortest path from start_node to end_node
validate_route(self, edges, **kwargs)
Given a list or set of Edge instances, verify that they result in a contiguous route
Not yet implemented.
sort(self, edges, **kwargs)
Given a list or set of Edge instances, sort them from root-side to leaf-side
Not yet implemented.
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 instance. Returns a tuple of the newly created rootside_edge (parent to the inserted node) and leafside_edge (child to the inserted node).
Process:
Add a new Edge from the parent Node of the current Edge instance to the provided Node instance, optionally cloning properties of the existing Edge.
Add a new Edge from the provided Node instance to the child Node of the current Edge instance, optionally cloning properties of the existing Edge.
Remove the original Edge instance.
- The instance will still exist in memory, though not in database (https://docs.djangoproject.com/en/3.1/ref/models/instances/#refreshing-objects-from-database). Recommend running the following after conducting the deletion:
del instancename
Cloning will fail if a field has unique=True, so a pre_save function can be passed into this method. Likewise, a post_save function can be passed in to rebuild relationships. For instance, if you have a name field that is unique and generated automatically in the model’s save() method, you could pass in a the following pre_save function to clear the name prior to saving the new Edge instance(s):
def pre_save(new_edge):
new_edge.name = ""
return new_edge
A more complete example, where we have models named NetworkEdge & NetworkNode, and we want to insert a new Node (n2) into Edge e1, while copying e1’s field properties (except name) to the newly created rootside Edge instance (n1 to n2) is shown below.
Original Final
n1 o n1 o
| \
| o n2
| /
n3 o n3 o
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()
# function to clear the `name` field, which is autogenerated and must be 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)