Skip to content

Commit 27f0216

Browse files
committed
update readme
1 parent 409e9cb commit 27f0216

1 file changed

Lines changed: 106 additions & 25 deletions

File tree

README.md

Lines changed: 106 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -52,55 +52,136 @@ The main benefits of `ltree`:
5252
python manage.py migrate django_ltree
5353
```
5454

55-
4. Alternatively you can avoid install the application, and create the the extensions with a custom migration in an app in your project.
55+
## Usage
56+
`django-ltree` provides a base model class called `TreeModel`.
5657

57-
```python
58-
from django.db import migrations
59-
from django_ltree.operations import LtreeExtension
58+
`TreeModel` does these things out of the box:
6059

61-
class Migration(migrations.Migration):
62-
initial = True
63-
dependencies = []
60+
* adds a field called `path` to your model
61+
* adds `t_objects` which is the `TreeManager` you can use to work with tree data
62+
* adds two indexes for `path` (one `BTreeIndex`, one `GistIndex`)
63+
* orders items base on `path`
64+
65+
if you are overriding the `Meta` class of your model, you may want to inherit from TreeModel.Meta.
66+
67+
```py
68+
class Meta(TreeModel.Meta):
69+
```
70+
71+
to keep the indexes and ordering.
6472

65-
operations = [LtreeExtension()]
66-
```
6773

6874
## Quick Start
6975

70-
1. Add a PathField to your model:
76+
1. inherit from TreeModel:
7177
```python
72-
from django_ltree.fields import PathField
78+
from django_ltree.models import TreeModel
7379

74-
class Category(models.Model):
80+
class Category(TreeModel):
7581
name = models.CharField(max_length=50)
76-
path = PathField()
7782
```
7883

84+
7985
2. Create tree nodes:
8086
```python
81-
root = Category.objects.create(name="Root", path="root")
82-
child = Category.objects.create(name="Child", path=f"{root.path}.child")
87+
# make an item without a parent (root)
88+
root = Category.t_objects.create(name="Root")
89+
# make a child item
90+
child = Category.t_objects.create_child(name="Child", parent=root)
91+
# you can also use `add_child` directly on root
92+
child2 = root.add_child(name="another child")
8393
```
8494

95+
note that `path` is handled by `django-ltree`, you don't need to pass any value for it
96+
8597
3. Query ancestors and descendants:
8698
```python
8799
# Get all ancestors
88-
Category.objects.filter(path__ancestor=child.path)
100+
child.ancestors()
89101

90102
# Get all descendants
91-
Category.objects.filter(path__descendant=root.path)
103+
child.descendants()
92104
```
93105

94-
## Migration Dependency
106+
### TreeModel methods
107+
`TreeModel` has the following methods:
108+
109+
1. `label(self)`: returns the last part of `path`
110+
111+
2. `ancestors(self)`: return all the ancestors of the current item
112+
113+
3. `descendants(self)`: return all the descendants of the current item
114+
115+
4. `parent(self)`: return the immediate parent of the current item
116+
117+
5. `get_root(self)`: return the root parent of this item
118+
119+
6. `children(self)`: return all the immediate children of the current item
120+
121+
7. `siblings(self)`: return all the siblings of the current item (items that share the same parent with this item)
122+
123+
8. `add_child(self, **kwargs)`: create a child for this item
124+
kwargs are the arguments used to make the child (the model fields)
125+
126+
9. `change_parent(self, new_parent)`: change the parent of the current item (this moves the item and all it's descendants to be under another item)
127+
new_parent is either a object of the same model, or the `path` value of an object
128+
129+
10. `make_root(self)`: move the current item to be a root item (moves the item and all it's descendants)
130+
131+
11. `delete(self, cascade=False, **kwargs)`: deletes the current item
132+
if cascade is True, all the descendants are also deleted, otherwise they will move to become the descendants of the first parent of the deleted item
133+
134+
12. `delete_cascade(self, **kwargs)`: delete the current item and all it's children
135+
136+
137+
### TreeManager methods
138+
`TreeManager` has the following methods
139+
1. `create_child(self, parent=None, **kwargs)`: creates an item
140+
if `parent` is provided, it will become the parent item of the created item, otherwise creation will happen as root
141+
`kwargs` are the model fields used to create the item
142+
143+
2. `create(self, **kwargs)`: create a root item
144+
`kwargs` are the model fields used to create the item
145+
146+
3. `roots(self)`: return all the root items from database
147+
148+
4. `children(self, path)`: return all the children of the specified `path`
149+
150+
151+
### lookups and functions
152+
for a list of all available operations and functions for ltree check https://www.postgresql.org/docs/current/ltree.html#LTREE-OPS-FUNCS
153+
154+
#### provided lookups:
155+
1. `exact` (same as `=` in postgresql)
156+
`TreeModel.t_objects.filter(path__exact=path)`
157+
158+
2. `ancestors` (same as `@>` in postgresql)
159+
`TreeModel.t_objects.filter(path__ancestors=path)`
160+
161+
3. `descendants` (same as `<@` in postgresql)
162+
`TreeModel.t_objects.filter(path__descendants=path)`
163+
164+
4. `match` (same as `~` in postgresql)
165+
`TreeModel.t_objects.filter(path__match=f"{self.path}.*{{1}}")`
166+
167+
5. `contains` (same as `?` in postgresql)
168+
`TreeModel.t_objects.filter(path__contains="1.*")`
169+
170+
6. `depth` (calls `NLEVEL` function from postgresql)
171+
`TreeModel.t_objects.filter(path__depth=len(path) + 1)`
172+
173+
#### provided functions
174+
1. `django_ltree.functions.NLevel`
175+
same as NLEVEL function from postgresql
176+
177+
2. `django_ltree.functions.Subpath`
178+
same as `SUBPATH` functions from postgresql
179+
180+
181+
for concatenation (`||`) you can use `django.db.models.functions.Concat`
182+
95183

96-
Include django_ltree as a dependency in your app's migrations:
97184

98-
```python
99-
class Migration(migrations.Migration):
100-
dependencies = [
101-
("django_ltree", "__latest__"),
102-
]
103-
```
104185

105186
## Known Issues
106187

0 commit comments

Comments
 (0)