1API
2===
3
4.. module:: treebeard.models
5
6.. inheritance-diagram:: Node
7.. autoclass:: Node
8  :show-inheritance:
9
10  This is the base class that defines the API of all tree models in this
11  library:
12
13     - :class:`treebeard.mp_tree.MP_Node` (materialized path)
14     - :class:`treebeard.ns_tree.NS_Node` (nested sets)
15     - :class:`treebeard.al_tree.AL_Node` (adjacency list)
16
17  .. warning::
18
19      Please be aware of the :doc:`caveats` when using this library.
20
21  .. automethod:: Node.add_root
22
23     Example:
24
25     .. code-block:: python
26
27        MyNode.add_root(numval=1, strval='abcd')
28
29     Or, to pass in an existing instance:
30
31     .. code-block:: python
32
33        new_node = MyNode(numval=1, strval='abcd')
34        MyNode.add_root(instance=new_node)
35
36  .. automethod:: add_child
37
38     Example:
39
40     .. code-block:: python
41
42        node.add_child(numval=1, strval='abcd')
43
44     Or, to pass in an existing instance:
45
46     .. code-block:: python
47
48        new_node = MyNode(numval=1, strval='abcd')
49        node.add_child(instance=new_node)
50
51  .. automethod:: add_sibling
52
53     Examples:
54
55     .. code-block:: python
56
57        node.add_sibling('sorted-sibling', numval=1, strval='abc')
58
59     Or, to pass in an existing instance:
60
61     .. code-block:: python
62
63        new_node = MyNode(numval=1, strval='abc')
64        node.add_sibling('sorted-sibling', instance=new_node)
65
66  .. automethod:: delete
67
68        .. note::
69
70           Call our queryset's delete to handle children removal. Subclasses
71           will handle extra maintenance.
72
73  .. automethod:: get_tree
74
75  .. automethod:: get_depth
76
77     Example:
78
79     .. code-block:: python
80
81        node.get_depth()
82
83  .. automethod:: get_ancestors
84
85     Example:
86
87     .. code-block:: python
88
89        node.get_ancestors()
90
91  .. automethod:: get_children
92
93     Example:
94
95     .. code-block:: python
96
97        node.get_children()
98
99  .. automethod:: get_children_count
100
101     Example:
102
103     .. code-block:: python
104
105        node.get_children_count()
106
107  .. automethod:: get_descendants
108
109     Example:
110
111     .. code-block:: python
112
113        node.get_descendants()
114
115  .. automethod:: get_descendant_count
116
117     Example:
118
119     .. code-block:: python
120
121        node.get_descendant_count()
122
123  .. automethod:: get_first_child
124
125     Example:
126
127     .. code-block:: python
128
129        node.get_first_child()
130
131  .. automethod:: get_last_child
132
133     Example:
134
135     .. code-block:: python
136
137        node.get_last_child()
138
139  .. automethod:: get_first_sibling
140
141     Example:
142
143     .. code-block:: python
144
145        node.get_first_sibling()
146
147  .. automethod:: get_last_sibling
148
149     Example:
150
151     .. code-block:: python
152
153        node.get_last_sibling()
154
155  .. automethod:: get_prev_sibling
156
157     Example:
158
159     .. code-block:: python
160
161        node.get_prev_sibling()
162
163  .. automethod:: get_next_sibling
164
165     Example:
166
167     .. code-block:: python
168
169        node.get_next_sibling()
170
171  .. automethod:: get_parent
172
173     Example:
174
175     .. code-block:: python
176
177        node.get_parent()
178
179  .. automethod:: get_root
180
181     Example:
182
183     .. code-block:: python
184
185        node.get_root()
186
187  .. automethod:: get_siblings
188
189     Example:
190
191     .. code-block:: python
192
193        node.get_siblings()
194
195  .. automethod:: is_child_of
196
197     Example:
198
199     .. code-block:: python
200
201        node.is_child_of(node2)
202
203  .. automethod:: is_descendant_of
204
205     Example:
206
207     .. code-block:: python
208
209        node.is_descendant_of(node2)
210
211  .. automethod:: is_sibling_of
212
213     Example:
214
215     .. code-block:: python
216
217        node.is_sibling_of(node2)
218
219  .. automethod:: is_root
220
221     Example:
222
223     .. code-block:: python
224
225        node.is_root()
226
227  .. automethod:: is_leaf
228
229     Example:
230
231     .. code-block:: python
232
233        node.is_leaf()
234
235  .. automethod:: move
236
237     .. note:: The node can be moved under another root node.
238
239     Examples:
240
241     .. code-block:: python
242
243        node.move(node2, 'sorted-child')
244        node.move(node2, 'prev-sibling')
245
246  .. automethod:: save
247
248  .. automethod:: get_first_root_node
249
250     Example:
251
252     .. code-block:: python
253
254        MyNodeModel.get_first_root_node()
255
256  .. automethod:: get_last_root_node
257
258     Example:
259
260     .. code-block:: python
261
262        MyNodeModel.get_last_root_node()
263
264  .. automethod:: get_root_nodes
265
266     Example:
267
268     .. code-block:: python
269
270        MyNodeModel.get_root_nodes()
271
272  .. automethod:: load_bulk
273
274     .. note::
275
276            Any internal data that you may have stored in your
277            nodes' data (:attr:`path`, :attr:`depth`) will be
278            ignored.
279
280     .. note::
281
282            If your node model has a ForeignKey this method will try to load
283            the related object before loading the data. If the related object
284            doesn't exist it won't load anything and will raise a DoesNotExist
285            exception. This is done because the dump_data method uses integers
286            to dump related objects.
287
288     .. note::
289
290            If your node model has :attr:`node_order_by` enabled, it will
291            take precedence over the order in the structure.
292
293     Example:
294
295     .. code-block:: python
296
297            data = [{'data':{'desc':'1'}},
298                    {'data':{'desc':'2'}, 'children':[
299                      {'data':{'desc':'21'}},
300                      {'data':{'desc':'22'}},
301                      {'data':{'desc':'23'}, 'children':[
302                        {'data':{'desc':'231'}},
303                      ]},
304                      {'data':{'desc':'24'}},
305                    ]},
306                    {'data':{'desc':'3'}},
307                    {'data':{'desc':'4'}, 'children':[
308                      {'data':{'desc':'41'}},
309                    ]},
310            ]
311            # parent = None
312            MyNodeModel.load_bulk(data, None)
313
314     Will create:
315
316     .. digraph:: load_bulk_digraph
317
318           "1";
319           "2";
320           "2" -> "21";
321           "2" -> "22";
322           "2" -> "23" -> "231";
323           "2" -> "24";
324           "3";
325           "4";
326           "4" -> "41";
327
328  .. automethod:: dump_bulk
329
330     Example:
331
332     .. code-block:: python
333
334        tree = MyNodeModel.dump_bulk()
335        branch = MyNodeModel.dump_bulk(node_obj)
336
337  .. automethod:: find_problems
338
339  .. automethod:: fix_tree
340
341  .. automethod:: get_descendants_group_count
342
343     Example:
344
345     .. code-block:: python
346
347            # get a list of the root nodes
348            root_nodes = MyModel.get_descendants_group_count()
349
350            for node in root_nodes:
351                print '%s by %s (%d replies)' % (node.comment, node.author,
352                                                 node.descendants_count)
353
354  .. automethod:: get_annotated_list
355
356
357     Example:
358
359     .. code-block:: python
360
361        annotated_list = MyModel.get_annotated_list()
362
363     With data:
364
365     .. digraph:: get_annotated_list_digraph
366
367              "a";
368              "a" -> "ab";
369              "ab" -> "aba";
370              "ab" -> "abb";
371              "ab" -> "abc";
372              "a" -> "ac";
373
374     Will return:
375
376     .. code-block:: python
377
378            [
379                (a,     {'open':True,  'close':[],    'level': 0})
380                (ab,    {'open':True,  'close':[],    'level': 1})
381                (aba,   {'open':True,  'close':[],    'level': 2})
382                (abb,   {'open':False, 'close':[],    'level': 2})
383                (abc,   {'open':False, 'close':[0,1], 'level': 2})
384                (ac,    {'open':False, 'close':[0],   'level': 1})
385            ]
386
387     This can be used with a template like:
388
389     .. code-block:: django
390
391            {% for item, info in annotated_list %}
392                {% if info.open %}
393                    <ul><li>
394                {% else %}
395                    </li><li>
396                {% endif %}
397
398                {{ item }}
399
400                {% for close in info.close %}
401                    </li></ul>
402                {% endfor %}
403            {% endfor %}
404
405     .. note::
406
407        This method was contributed originally by
408        `Alexey Kinyov <rudi@05bit.com>`_, using an idea borrowed from
409        `django-mptt`_.
410
411     .. versionadded:: 1.55
412
413
414  .. automethod:: get_annotated_list_qs
415
416  .. automethod:: get_database_vendor
417
418     Example:
419
420     .. code-block:: python
421
422        MyNodeModel.get_database_vendor("write")
423
424
425     .. versionadded:: 1.61
426
427
428.. _django-mptt: https://github.com/django-mptt/django-mptt/