@@ -26,10 +26,12 @@ Features and limitations
2626- The fields added by the common table expression always are
2727 ``tree_depth ``, ``tree_path `` and ``tree_ordering ``. The names cannot
2828 be changed. ``tree_depth `` is an integer, ``tree_path `` an array of
29- primary keys and ``tree_ordering `` an array of values used for
30- ordering nodes within their siblings. Note that the contents of the
31- ``tree_path `` and ``tree_ordering `` are subject to change. You shouldn't rely
32- on their contents.
29+ primary keys representing the path from the root to the current node
30+ (including the current node itself), and ``tree_ordering `` an array of
31+ values used for ordering nodes within their siblings at each level of
32+ the tree hierarchy. Note that the contents of the ``tree_path `` and
33+ ``tree_ordering `` are subject to change. You shouldn't rely on their
34+ contents.
3335- Besides adding the fields mentioned above the package only adds queryset
3436 methods for ordering siblings and filtering ancestors and descendants. Other
3537 features may be useful, but will not be added to the package just because
@@ -182,6 +184,53 @@ Basic usage
182184 nodes = Node.objects.with_tree_fields().without_tree_fields()
183185
184186
187+ Understanding tree fields
188+ -------------------------
189+
190+ When using ``with_tree_fields() ``, each node gets three additional attributes:
191+
192+ - **``tree_depth`` **: An integer representing the depth of the node in the tree
193+ (root nodes have depth 0)
194+ - **``tree_path`` **: An array containing the primary keys of all ancestors plus
195+ the current node itself, representing the path from root to current node
196+ - **``tree_ordering`` **: An array containing the ordering/ranking values used
197+ for sibling ordering at each level of the tree hierarchy
198+
199+ The key difference between ``tree_path `` and ``tree_ordering ``:
200+
201+ .. code-block :: python
202+
203+ # Example tree structure:
204+ # Root (pk=1, order=0)
205+ # ├── Child A (pk=2, order=10)
206+ # │ └── Grandchild (pk=4, order=5)
207+ # └── Child B (pk=3, order=20)
208+
209+ # For the Grandchild node:
210+ grandchild = Node.objects.with_tree_fields().get(pk = 4 )
211+
212+ # tree_path shows the route through primary keys: Root -> Child A -> Grandchild
213+ assert grandchild.tree_path == [1 , 2 , 4 ] # [root.pk, child_a.pk, grandchild.pk]
214+
215+ # tree_ordering shows ordering values at each level: Root's order, Child A's order, Grandchild's order
216+ assert grandchild.tree_ordering == [0 , 10 , 5 ] # [root.order, child_a.order, grandchild.order]
217+
218+ **Important note **: When not using an explicit ordering (like a ``position ``
219+ field), siblings are ordered by their primary key by default. This means
220+ ``tree_path `` and ``tree_ordering `` will contain the same values. While this
221+ may be fine for your use case consider adding an explicit ordering field:
222+
223+ .. code-block :: python
224+
225+ class Node (TreeNode ):
226+ id = models.UUIDField(primary_key = True , default = uuid.uuid4)
227+ name = models.CharField(max_length = 100 )
228+ position = models.PositiveIntegerField(default = 0 )
229+
230+ class Meta :
231+ ordering = [" position" ]
232+
233+
185234 Filtering tree subsets
186235----------------------
187236
0 commit comments