Bases: django.db.models.base.Model
Node class
This is the base class that defines the API of all tree models in this library:
- treebeard.mp_tree.MP_Node (materialized path)
- treebeard.ns_tree.NS_Node (nested sets)
- treebeard.al_tree.AL_Node (adjacency list)
Warning
Please note that django-treebeard uses Django raw SQL queries for some write operations, and raw queries don’t update the objects in the ORM since it’s being bypassed.
Because of this, if you have a node in memory and plan to use it after a tree modification (adding/removing/moving nodes), you need to reload it.
Adds a root node to the tree. The new root node will be the new rightmost root node. If you want to insert a root node at a specific position, use add_sibling() in an already existing root node instead.
Parameter: | **kwargs – object creation data that will be passed to the inherited Node model |
---|---|
Returns: | the created node object. It will be save()d by this method. |
Example:
MyNode.add_root(numval=1, strval='abcd')
Adds a child to the node. The new node will be the new rightmost child. If you want to insert a node at a specific position, use the add_sibling() method of an already existing child node instead.
Parameter: | **kwargs – Object creation data that will be passed to the inherited Node model |
---|---|
Returns: | The created node object. It will be save()d by this method. |
Example:
node.add_child(numval=1, strval='abcd')
Adds a new node as a sibling to the current node object.
Parameters: |
|
---|---|
Returns: | The created node object. It will be saved by this method. |
Raises InvalidPosition: | |
when passing an invalid pos parm |
|
Raises InvalidPosition: | |
when node_order_by is enabled and the pos parm wasn’t sorted-sibling |
|
Raises MissingNodeOrderBy: | |
when passing sorted-sibling as pos and the node_order_by attribute is missing |
Examples:
node.add_sibling('sorted-sibling', numval=1, strval='abc')
Removes a node and all it’s descendants.
Note
Call our queryset’s delete to handle children removal. Subclasses will handle extra maintenance.
Returns: | A list of nodes ordered as DFS, including the parent. If no parent is given, the entire tree is returned. |
---|
Returns: | the depth (level) of the node |
---|
Example:
node.get_depth()
Returns: | A queryset containing the current node object’s ancestors, starting by the root node and descending to the parent. (some subclasses may return a list) |
---|
Example:
node.get_ancestors()
Returns: | A queryset of all the node’s children |
---|
Example:
node.get_children()
Returns: | The number of the node’s children |
---|
Example:
node.get_children_count()
Returns: | A queryset of all the node’s descendants, doesn’t include the node itself (some subclasses may return a list). |
---|
Example:
node.get_descendants()
Returns: | the number of descendants of a node. |
---|
Example:
node.get_descendant_count()
Returns: | The leftmost node’s child, or None if it has no children. |
---|
Example:
node.get_first_child()
Returns: | The rightmost node’s child, or None if it has no children. |
---|
Example:
node.get_last_child()
Returns: | The leftmost node’s sibling, can return the node itself if it was the leftmost sibling. |
---|
Example:
node.get_first_sibling()
Returns: | The rightmost node’s sibling, can return the node itself if it was the rightmost sibling. |
---|
Example:
node.get_last_sibling()
Returns: | The previous node’s sibling, or None if it was the leftmost sibling. |
---|
Example:
node.get_prev_sibling()
Returns: | The next node’s sibling, or None if it was the rightmost sibling. |
---|
Example:
node.get_next_sibling()
Returns: | the parent node of the current node object. Caches the result in the object itself to help in loops. |
---|---|
Parameter: | update – Updates de cached value. |
Example:
node.get_parent()
Returns: | the root node for the current node object. |
---|
Example:
node.get_root()
Returns: | A queryset of all the node’s siblings, including the node itself. |
---|
Example:
node.get_siblings()
Returns: | True if the node is a child of another node given as an argument, else, returns False |
---|---|
Parameter: | node – The node that will be checked as a parent |
Example:
node.is_child_of(node2)
Returns: | True if the node if a descendant of another node given as an argument, else, returns False |
---|---|
Parameter: | node – The node that will be checked as an ancestor |
Example:
node.is_descendant_of(node2)
Returns: | True if the node if a sibling of another node given as an argument, else, returns False |
---|---|
Parameter: | node – The node that will be checked as a sibling |
Example:
node.is_sibling_of(node2)
Returns: | True if the node is a root node (else, returns False) |
---|
Example:
node.is_root()
Returns: | True if the node is a leaf node (else, returns False) |
---|
Example:
node.is_leaf()
Moves the current node and all it’s descendants to a new position relative to another node.
Parameters: |
|
---|---|
Returns: | None |
Raises InvalidPosition: | |
when passing an invalid pos parm |
|
Raises InvalidPosition: | |
when node_order_by is enabled and the pos parm wasn’t sorted-sibling or sorted-child |
|
Raises InvalidMoveToDescendant: | |
when trying to move a node to one of it’s own descendants |
|
Raises PathOverflow: | |
when the library can’t make room for the node’s new position |
|
Raises MissingNodeOrderBy: | |
when passing sorted-sibling or sorted-child as pos and the node_order_by attribute is missing |
Note
The node can be moved under another root node.
Examples:
node.move(node2, 'sorted-child')
node.move(node2, 'prev-sibling')
Saves the current instance. Override this in a subclass if you want to control the saving process.
The ‘force_insert’ and ‘force_update’ parameters can be used to insist that the “save” must be an SQL insert or update (or equivalent for non-SQL backends), respectively. Normally, they should not be set.
Returns: | The first root node in the tree or None if it is empty |
---|
Example:
MyNodeModel.get_first_root_node()
Returns: | The last root node in the tree or None if it is empty |
---|
Example:
MyNodeModel.get_last_root_node()
Returns: | A queryset containing the root nodes in the tree. |
---|
Example:
MyNodeModel.get_root_nodes()
Loads a list/dictionary structure to the tree.
Parameters: |
|
---|---|
Returns: | A list of the added node ids. |
Note
Any internal data that you may have stored in your nodes’ data (path, depth) will be ignored.
Note
If your node model has node_order_by enabled, it will take precedence over the order in the structure.
Example:
data = [{'data':{'desc':'1'}},
{'data':{'desc':'2'}, 'children':[
{'data':{'desc':'21'}},
{'data':{'desc':'22'}},
{'data':{'desc':'23'}, 'children':[
{'data':{'desc':'231'}},
]},
{'data':{'desc':'24'}},
]},
{'data':{'desc':'3'}},
{'data':{'desc':'4'}, 'children':[
{'data':{'desc':'41'}},
]},
]
# parent = None
MyNodeModel.load_data(data, None)
Will create:
Dumps a tree branch to a python data structure.
Parameters: |
|
---|---|
Returns: | A python data structure, describen with detail in load_bulk() |
Example:
tree = MyNodeModel.dump_bulk()
branch = MyNodeModel.dump_bulk(node_obj)
Helper for a very common case: get a group of siblings and the number of descendants (not only children) in every sibling.
Parameter: | parent – The parent of the siblings to return. If no parent is given, the root nodes will be returned. |
---|---|
Returns: | A list (NOT a Queryset) of node objects with an extra attribute: descendants_count. |
Example:
# get a list of the root nodes
root_nodes = MyModel.get_descendants_group_count()
for node in root_nodes:
print '%s by %s (%d replies)' % (node.comment, node.author,
node.descendants_count)
Gets an annotated list from a tree branch.
Parameter: | parent – The node whose descendants will be annotated. The node itself will be included in the list. If not given, the entire tree will be annotated. |
---|
Example:
annotated_list = get_annotated_list()
With data:
Will return:
[
(a, {'open':True, 'close':[], 'level': 0})
(ab, {'open':True, 'close':[], 'level': 1})
(aba, {'open':True, 'close':[], 'level': 2})
(abb, {'open':False, 'close':[], 'level': 2})
(abc, {'open':False, 'close':[0,1], 'level': 2})
(ac, {'open':False, 'close':[0], 'level': 1})
]
This can be used with a template like:
{% for item, info in annotated_list %}
{% if info.open %}
<ul><li>
{% else %}
</li><li>
{% endif %}
{{ item }}
{% for close in info.close %}
</li></ul>
{% endfor %}
{% endfor %}
Note
This method was contributed originally by Alexey Kinyov, using an idea borrowed from django-mptt.
New in version 1.55.
Returns the supported database engine used by a treebeard model.
This will return the default database engine depending on the version of Django. If you use something different, like a non-default database in Django 1.2+, you need to override this method and return the correct engine.
Returns: | postgresql, postgresql_psycopg2, mysql or sqlite3 |
---|
Example:
@classmethod
def get_database_engine(cls):
return "mysql"
New in version 1.61.