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/