django-fast-treenode 3.0.1__tar.gz → 3.0.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/LICENSE +1 -0
- {django_fast_treenode-3.0.1/django_fast_treenode.egg-info → django_fast_treenode-3.0.3}/PKG-INFO +24 -24
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/README.md +22 -23
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3/django_fast_treenode.egg-info}/PKG-INFO +24 -24
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/docs/about.md +1 -1
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/docs/index.md +12 -12
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/docs/migration.md +4 -4
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/docs/roadmap.md +2 -6
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/pyproject.toml +2 -1
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/setup.py +2 -1
- django_fast_treenode-3.0.3/tests/test_suite.py +99 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/admin/admin.py +1 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/managers/queries.py +43 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/models/mixins/descendants.py +17 -11
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/static/vendors/jquery-ui/AUTHORS.txt +384 -384
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/static/vendors/jquery-ui/LICENSE.txt +43 -43
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/static/vendors/jquery-ui/external/jquery/jquery.js +10716 -10716
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/static/vendors/jquery-ui/index.html +297 -297
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/static/vendors/jquery-ui/jquery-ui.css +438 -438
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/static/vendors/jquery-ui/jquery-ui.js +5222 -5222
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/static/vendors/jquery-ui/jquery-ui.min.css +6 -6
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/static/vendors/jquery-ui/jquery-ui.min.js +5 -5
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/static/vendors/jquery-ui/jquery-ui.structure.css +16 -16
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/static/vendors/jquery-ui/jquery-ui.structure.min.css +4 -4
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/static/vendors/jquery-ui/jquery-ui.theme.css +439 -439
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/static/vendors/jquery-ui/jquery-ui.theme.min.css +4 -4
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/static/vendors/jquery-ui/package.json +82 -82
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/utils/db/compiler.py +24 -25
- django_fast_treenode-3.0.3/treenode/utils/db/sqlcompat.py +145 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/version.py +2 -3
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/views/crud.py +31 -10
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/widgets.py +2 -0
- django_fast_treenode-3.0.1/tests/test_suite.py +0 -91
- django_fast_treenode-3.0.1/treenode/utils/db/sqlcompat.py +0 -60
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/MANIFEST.in +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/django_fast_treenode.egg-info/SOURCES.txt +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/django_fast_treenode.egg-info/dependency_links.txt +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/django_fast_treenode.egg-info/requires.txt +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/django_fast_treenode.egg-info/top_level.txt +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/docs/.gitignore +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/docs/.nojekyll +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/docs/admin.md +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/docs/api.md +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/docs/apifirst.md +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/docs/cache.md +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/docs/customization.md +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/docs/dnd.md +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/docs/import_export.md +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/docs/insert-after.jpg +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/docs/insert-as-child.jpg +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/docs/installation.md +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/docs/models.md +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/docs/requirements.txt +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/docs/using.md +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/setup.cfg +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/__init__.py +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/admin/__init__.py +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/admin/changelist.py +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/admin/exporter.py +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/admin/importer.py +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/admin/mixin.py +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/apps.py +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/cache.py +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/forms.py +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/managers/__init__.py +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/managers/managers.py +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/managers/tasks.py +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/models/__init__.py +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/models/decorators.py +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/models/factory.py +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/models/mixins/__init__.py +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/models/mixins/ancestors.py +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/models/mixins/children.py +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/models/mixins/family.py +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/models/mixins/logical.py +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/models/mixins/node.py +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/models/mixins/properties.py +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/models/mixins/roots.py +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/models/mixins/siblings.py +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/models/mixins/tree.py +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/models/mixins/update.py +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/models/models.py +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/settings.py +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/signals.py +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/static/.gitkeep +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/static/css/.gitkeep +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/static/css/tree_widget.css +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/static/css/treenode_admin.css +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/static/css/treenode_tabs.css +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/static/js/.gitkeep +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/static/js/lz-string.min.js +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/static/js/tree_widget.js +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/static/js/treenode_admin.js +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/static/vendors/jquery-ui/images/ui-icons_444444_256x240.png +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/static/vendors/jquery-ui/images/ui-icons_555555_256x240.png +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/static/vendors/jquery-ui/images/ui-icons_777620_256x240.png +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/static/vendors/jquery-ui/images/ui-icons_777777_256x240.png +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/static/vendors/jquery-ui/images/ui-icons_cc0000_256x240.png +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/static/vendors/jquery-ui/images/ui-icons_ffffff_256x240.png +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/templates/.gitkeep +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/templates/admin/.gitkeep +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/templates/admin/treenode_ajax_rows.html +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/templates/admin/treenode_changelist.html +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/templates/admin/treenode_import_export.html +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/templates/admin/treenode_rows.html +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/templates/widgets/tree_widget.html +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/tests.py +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/urls.py +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/utils/__init__.py +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/utils/db/__init__.py +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/utils/db/db_vendor.py +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/utils/db/service.py +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/utils/db/sqlquery.py +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/views/__init__.py +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/views/autoapi.py +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/views/autocomplete.py +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/views/children.py +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/views/common.py +0 -0
- {django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3}/treenode/views/search.py +0 -0
{django_fast_treenode-3.0.1/django_fast_treenode.egg-info → django_fast_treenode-3.0.3}/PKG-INFO
RENAMED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: django-fast-treenode
|
3
|
-
Version: 3.0.
|
3
|
+
Version: 3.0.3
|
4
4
|
Summary: Treenode Framework for supporting tree (hierarchical) data structure in Django projects
|
5
5
|
Home-page: https://django-fast-treenode.readthedocs.io/
|
6
6
|
Author: Timur Kady
|
@@ -27,6 +27,7 @@ License: MIT License
|
|
27
27
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
28
28
|
SOFTWARE.
|
29
29
|
|
30
|
+
|
30
31
|
Project-URL: Homepage, https://github.com/TimurKady/django-fast-treenode
|
31
32
|
Project-URL: Documentation, https://django-fast-treenode.readthedocs.io/
|
32
33
|
Project-URL: Source, https://github.com/TimurKady/django-fast-treenode
|
@@ -61,16 +62,16 @@ Dynamic: home-page
|
|
61
62
|
Dynamic: license-file
|
62
63
|
Dynamic: requires-python
|
63
64
|
|
64
|
-
#
|
65
|
+
# Treenode Framework
|
65
66
|
**A hybrid open-source framework for working with trees in Django**
|
66
67
|
|
67
68
|
[](https://github.com/TimurKady/django-fast-treenode/actions/workflows/test.yaml)
|
68
69
|
[](https://django-fast-treenode.readthedocs.io/)
|
69
|
-
[](https://pypi.org/project/django-fast-
|
70
|
+
[](https://pypi.org/project/django-fast-Treenode/)
|
70
71
|
[](https://djangopackages.org/packages/p/django-fast-treenode/)
|
71
72
|
[](https://github.com/sponsors/TimurKady)
|
72
73
|
|
73
|
-
## About The
|
74
|
+
## About The Treenode Framework
|
74
75
|
### Overview
|
75
76
|
|
76
77
|
**Treenode Framework** is an advanced tree management system for Django applications.It is designed to handle large-scale, deeply nested, and highly dynamic tree structures while maintaining excellent performance, data integrity, and ease of use.
|
@@ -86,7 +87,7 @@ Its core philosophy: **maximum scalability, minimum complexity**.
|
|
86
87
|
|
87
88
|
### Key Features
|
88
89
|
#### Common operations
|
89
|
-
The `django-fast-
|
90
|
+
The `django-fast-Treenode` package supports all the basic operations needed to work with tree structures:
|
90
91
|
|
91
92
|
- Extracting **ancestors** (queryset, list, pks, count);
|
92
93
|
- Extracting **children** (queryset, list, pks, count);
|
@@ -117,10 +118,10 @@ Typical applications include:
|
|
117
118
|
|
118
119
|
In all these domains, scalable and fast tree management is not a luxury — it's a necessity.
|
119
120
|
|
120
|
-
### Why
|
121
|
+
### Why Treenode Framework?
|
121
122
|
At the moment, django-fast-treeenode is, if not the best, then one of the best packages for working with tree data under Djangjo.
|
122
123
|
|
123
|
-
- **High performance**: [tests show](docs/about.md#benchmark-tests) that on trees of 5k-10k nodes with a nesting depth of 500-600 levels, **Treenode Framework** (`django-fast-
|
124
|
+
- **High performance**: [tests show](docs/about.md#benchmark-tests) that on trees of 5k-10k nodes with a nesting depth of 500-600 levels, **Treenode Framework** (`django-fast-Treenode`) shows **performance 4-7 times better** than the main popular packages.
|
124
125
|
- **Flexible API**: today contains the widest set of methods for working with a tree in comparison with other packages.
|
125
126
|
- **Convenient administration**: the admin panel interface was developed taking into account the experience of using other packages. It provides convenience and intuitiveness with ease of programming.
|
126
127
|
- **Scalability**: **Treenode Framework** suitable for solving simple problems such as menus, directories, parsing arithmetic expressions, as well as complex problems such as program optimization, image layout, multi-step decision making problems, or machine learning..
|
@@ -133,7 +134,7 @@ To get started quickly, you need to follow these steps:
|
|
133
134
|
|
134
135
|
- Simply install the package via `pip`:
|
135
136
|
```sh
|
136
|
-
pip install django-fast-
|
137
|
+
pip install django-fast-Treenode
|
137
138
|
```
|
138
139
|
- Once installed, add `'treenode'` to your `INSTALLED_APPS` in **settings.py**:
|
139
140
|
```python {title="settings.py"}
|
@@ -146,9 +147,9 @@ To get started quickly, you need to follow these steps:
|
|
146
147
|
|
147
148
|
- Open **models.py** and create your own tree class:
|
148
149
|
```
|
149
|
-
from
|
150
|
+
from Treenode.models import TreenodeModel
|
150
151
|
|
151
|
-
class MyTree(
|
152
|
+
class MyTree(TreenodeModel):
|
152
153
|
name = models.CharField(max_length=255)
|
153
154
|
display_field = "name"
|
154
155
|
```
|
@@ -156,11 +157,11 @@ To get started quickly, you need to follow these steps:
|
|
156
157
|
- Open **admin.py** and create a model for the admin panel
|
157
158
|
```
|
158
159
|
from django.contrib import admin
|
159
|
-
from
|
160
|
-
from .models import
|
160
|
+
from Treenode.admin import TreenodeModelAdmin
|
161
|
+
from .models import MyTree
|
161
162
|
|
162
|
-
@admin.register(
|
163
|
-
class
|
163
|
+
@admin.register(MyTree)
|
164
|
+
class MyTreeAdmin(TreenodeModelAdmin):
|
164
165
|
list_display = ("name",)
|
165
166
|
search_fields = ("name",)
|
166
167
|
```
|
@@ -175,25 +176,24 @@ To get started quickly, you need to follow these steps:
|
|
175
176
|
```sh
|
176
177
|
python manage.py runserver
|
177
178
|
```
|
178
|
-
|
179
179
|
Everything is ready, enjoy 🎉!
|
180
180
|
|
181
181
|
## Documentation
|
182
|
-
Full documentation is available at **[ReadTheDocs](https://django-fast-
|
182
|
+
Full documentation is available at **[ReadTheDocs](https://django-fast-Treenode.readthedocs.io/)**.
|
183
183
|
|
184
184
|
Quick access links:
|
185
|
-
* [Installation, configuration and fine tuning](https://django-fast-
|
186
|
-
* [Model Inheritance and Extensions](https://django-fast-
|
187
|
-
* [Working with Admin Classes](https://django-fast-
|
188
|
-
* [API Reference](https://django-fast-
|
189
|
-
* [Import & Export](https://django-fast-
|
190
|
-
* [Caching and working with cache](https://django-fast-
|
191
|
-
* [Migration and upgrade guide](https://django-fast-
|
185
|
+
* [Installation, configuration and fine tuning](https://django-fast-Treenode.readthedocs.io/installation/)
|
186
|
+
* [Model Inheritance and Extensions](https://django-fast-Treenode.readthedocs.io/models/)
|
187
|
+
* [Working with Admin Classes](https://django-fast-Treenode.readthedocs.io/admin/)
|
188
|
+
* [API Reference](https://django-fast-Treenode.readthedocs.io/api/)
|
189
|
+
* [Import & Export](https://django-fast-Treenode.readthedocs.io/import_export/)
|
190
|
+
* [Caching and working with cache](https://django-fast-Treenode.readthedocs.io/cache/)
|
191
|
+
* [Migration and upgrade guide](https://django-fast-Treenode.readthedocs.io/migration/)
|
192
192
|
|
193
193
|
Your wishes, objections, comments are welcome.
|
194
194
|
|
195
195
|
## License
|
196
|
-
Released under [MIT License](https://github.com/TimurKady/django-fast-
|
196
|
+
Released under [MIT License](https://github.com/TimurKady/django-fast-Treenode/blob/main/LICENSE).
|
197
197
|
|
198
198
|
## Credits
|
199
199
|
Thanks to everyone who contributed to the development and testing of this package, as well as the Django community for their inspiration and support.
|
@@ -1,13 +1,13 @@
|
|
1
|
-
#
|
1
|
+
# Treenode Framework
|
2
2
|
**A hybrid open-source framework for working with trees in Django**
|
3
3
|
|
4
4
|
[](https://github.com/TimurKady/django-fast-treenode/actions/workflows/test.yaml)
|
5
5
|
[](https://django-fast-treenode.readthedocs.io/)
|
6
|
-
[](https://pypi.org/project/django-fast-
|
6
|
+
[](https://pypi.org/project/django-fast-Treenode/)
|
7
7
|
[](https://djangopackages.org/packages/p/django-fast-treenode/)
|
8
8
|
[](https://github.com/sponsors/TimurKady)
|
9
9
|
|
10
|
-
## About The
|
10
|
+
## About The Treenode Framework
|
11
11
|
### Overview
|
12
12
|
|
13
13
|
**Treenode Framework** is an advanced tree management system for Django applications.It is designed to handle large-scale, deeply nested, and highly dynamic tree structures while maintaining excellent performance, data integrity, and ease of use.
|
@@ -23,7 +23,7 @@ Its core philosophy: **maximum scalability, minimum complexity**.
|
|
23
23
|
|
24
24
|
### Key Features
|
25
25
|
#### Common operations
|
26
|
-
The `django-fast-
|
26
|
+
The `django-fast-Treenode` package supports all the basic operations needed to work with tree structures:
|
27
27
|
|
28
28
|
- Extracting **ancestors** (queryset, list, pks, count);
|
29
29
|
- Extracting **children** (queryset, list, pks, count);
|
@@ -54,10 +54,10 @@ Typical applications include:
|
|
54
54
|
|
55
55
|
In all these domains, scalable and fast tree management is not a luxury — it's a necessity.
|
56
56
|
|
57
|
-
### Why
|
57
|
+
### Why Treenode Framework?
|
58
58
|
At the moment, django-fast-treeenode is, if not the best, then one of the best packages for working with tree data under Djangjo.
|
59
59
|
|
60
|
-
- **High performance**: [tests show](docs/about.md#benchmark-tests) that on trees of 5k-10k nodes with a nesting depth of 500-600 levels, **Treenode Framework** (`django-fast-
|
60
|
+
- **High performance**: [tests show](docs/about.md#benchmark-tests) that on trees of 5k-10k nodes with a nesting depth of 500-600 levels, **Treenode Framework** (`django-fast-Treenode`) shows **performance 4-7 times better** than the main popular packages.
|
61
61
|
- **Flexible API**: today contains the widest set of methods for working with a tree in comparison with other packages.
|
62
62
|
- **Convenient administration**: the admin panel interface was developed taking into account the experience of using other packages. It provides convenience and intuitiveness with ease of programming.
|
63
63
|
- **Scalability**: **Treenode Framework** suitable for solving simple problems such as menus, directories, parsing arithmetic expressions, as well as complex problems such as program optimization, image layout, multi-step decision making problems, or machine learning..
|
@@ -70,7 +70,7 @@ To get started quickly, you need to follow these steps:
|
|
70
70
|
|
71
71
|
- Simply install the package via `pip`:
|
72
72
|
```sh
|
73
|
-
pip install django-fast-
|
73
|
+
pip install django-fast-Treenode
|
74
74
|
```
|
75
75
|
- Once installed, add `'treenode'` to your `INSTALLED_APPS` in **settings.py**:
|
76
76
|
```python {title="settings.py"}
|
@@ -83,9 +83,9 @@ To get started quickly, you need to follow these steps:
|
|
83
83
|
|
84
84
|
- Open **models.py** and create your own tree class:
|
85
85
|
```
|
86
|
-
from
|
86
|
+
from Treenode.models import TreenodeModel
|
87
87
|
|
88
|
-
class MyTree(
|
88
|
+
class MyTree(TreenodeModel):
|
89
89
|
name = models.CharField(max_length=255)
|
90
90
|
display_field = "name"
|
91
91
|
```
|
@@ -93,11 +93,11 @@ To get started quickly, you need to follow these steps:
|
|
93
93
|
- Open **admin.py** and create a model for the admin panel
|
94
94
|
```
|
95
95
|
from django.contrib import admin
|
96
|
-
from
|
97
|
-
from .models import
|
96
|
+
from Treenode.admin import TreenodeModelAdmin
|
97
|
+
from .models import MyTree
|
98
98
|
|
99
|
-
@admin.register(
|
100
|
-
class
|
99
|
+
@admin.register(MyTree)
|
100
|
+
class MyTreeAdmin(TreenodeModelAdmin):
|
101
101
|
list_display = ("name",)
|
102
102
|
search_fields = ("name",)
|
103
103
|
```
|
@@ -112,25 +112,24 @@ To get started quickly, you need to follow these steps:
|
|
112
112
|
```sh
|
113
113
|
python manage.py runserver
|
114
114
|
```
|
115
|
-
|
116
115
|
Everything is ready, enjoy 🎉!
|
117
116
|
|
118
117
|
## Documentation
|
119
|
-
Full documentation is available at **[ReadTheDocs](https://django-fast-
|
118
|
+
Full documentation is available at **[ReadTheDocs](https://django-fast-Treenode.readthedocs.io/)**.
|
120
119
|
|
121
120
|
Quick access links:
|
122
|
-
* [Installation, configuration and fine tuning](https://django-fast-
|
123
|
-
* [Model Inheritance and Extensions](https://django-fast-
|
124
|
-
* [Working with Admin Classes](https://django-fast-
|
125
|
-
* [API Reference](https://django-fast-
|
126
|
-
* [Import & Export](https://django-fast-
|
127
|
-
* [Caching and working with cache](https://django-fast-
|
128
|
-
* [Migration and upgrade guide](https://django-fast-
|
121
|
+
* [Installation, configuration and fine tuning](https://django-fast-Treenode.readthedocs.io/installation/)
|
122
|
+
* [Model Inheritance and Extensions](https://django-fast-Treenode.readthedocs.io/models/)
|
123
|
+
* [Working with Admin Classes](https://django-fast-Treenode.readthedocs.io/admin/)
|
124
|
+
* [API Reference](https://django-fast-Treenode.readthedocs.io/api/)
|
125
|
+
* [Import & Export](https://django-fast-Treenode.readthedocs.io/import_export/)
|
126
|
+
* [Caching and working with cache](https://django-fast-Treenode.readthedocs.io/cache/)
|
127
|
+
* [Migration and upgrade guide](https://django-fast-Treenode.readthedocs.io/migration/)
|
129
128
|
|
130
129
|
Your wishes, objections, comments are welcome.
|
131
130
|
|
132
131
|
## License
|
133
|
-
Released under [MIT License](https://github.com/TimurKady/django-fast-
|
132
|
+
Released under [MIT License](https://github.com/TimurKady/django-fast-Treenode/blob/main/LICENSE).
|
134
133
|
|
135
134
|
## Credits
|
136
135
|
Thanks to everyone who contributed to the development and testing of this package, as well as the Django community for their inspiration and support.
|
{django_fast_treenode-3.0.1 → django_fast_treenode-3.0.3/django_fast_treenode.egg-info}/PKG-INFO
RENAMED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: django-fast-treenode
|
3
|
-
Version: 3.0.
|
3
|
+
Version: 3.0.3
|
4
4
|
Summary: Treenode Framework for supporting tree (hierarchical) data structure in Django projects
|
5
5
|
Home-page: https://django-fast-treenode.readthedocs.io/
|
6
6
|
Author: Timur Kady
|
@@ -27,6 +27,7 @@ License: MIT License
|
|
27
27
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
28
28
|
SOFTWARE.
|
29
29
|
|
30
|
+
|
30
31
|
Project-URL: Homepage, https://github.com/TimurKady/django-fast-treenode
|
31
32
|
Project-URL: Documentation, https://django-fast-treenode.readthedocs.io/
|
32
33
|
Project-URL: Source, https://github.com/TimurKady/django-fast-treenode
|
@@ -61,16 +62,16 @@ Dynamic: home-page
|
|
61
62
|
Dynamic: license-file
|
62
63
|
Dynamic: requires-python
|
63
64
|
|
64
|
-
#
|
65
|
+
# Treenode Framework
|
65
66
|
**A hybrid open-source framework for working with trees in Django**
|
66
67
|
|
67
68
|
[](https://github.com/TimurKady/django-fast-treenode/actions/workflows/test.yaml)
|
68
69
|
[](https://django-fast-treenode.readthedocs.io/)
|
69
|
-
[](https://pypi.org/project/django-fast-
|
70
|
+
[](https://pypi.org/project/django-fast-Treenode/)
|
70
71
|
[](https://djangopackages.org/packages/p/django-fast-treenode/)
|
71
72
|
[](https://github.com/sponsors/TimurKady)
|
72
73
|
|
73
|
-
## About The
|
74
|
+
## About The Treenode Framework
|
74
75
|
### Overview
|
75
76
|
|
76
77
|
**Treenode Framework** is an advanced tree management system for Django applications.It is designed to handle large-scale, deeply nested, and highly dynamic tree structures while maintaining excellent performance, data integrity, and ease of use.
|
@@ -86,7 +87,7 @@ Its core philosophy: **maximum scalability, minimum complexity**.
|
|
86
87
|
|
87
88
|
### Key Features
|
88
89
|
#### Common operations
|
89
|
-
The `django-fast-
|
90
|
+
The `django-fast-Treenode` package supports all the basic operations needed to work with tree structures:
|
90
91
|
|
91
92
|
- Extracting **ancestors** (queryset, list, pks, count);
|
92
93
|
- Extracting **children** (queryset, list, pks, count);
|
@@ -117,10 +118,10 @@ Typical applications include:
|
|
117
118
|
|
118
119
|
In all these domains, scalable and fast tree management is not a luxury — it's a necessity.
|
119
120
|
|
120
|
-
### Why
|
121
|
+
### Why Treenode Framework?
|
121
122
|
At the moment, django-fast-treeenode is, if not the best, then one of the best packages for working with tree data under Djangjo.
|
122
123
|
|
123
|
-
- **High performance**: [tests show](docs/about.md#benchmark-tests) that on trees of 5k-10k nodes with a nesting depth of 500-600 levels, **Treenode Framework** (`django-fast-
|
124
|
+
- **High performance**: [tests show](docs/about.md#benchmark-tests) that on trees of 5k-10k nodes with a nesting depth of 500-600 levels, **Treenode Framework** (`django-fast-Treenode`) shows **performance 4-7 times better** than the main popular packages.
|
124
125
|
- **Flexible API**: today contains the widest set of methods for working with a tree in comparison with other packages.
|
125
126
|
- **Convenient administration**: the admin panel interface was developed taking into account the experience of using other packages. It provides convenience and intuitiveness with ease of programming.
|
126
127
|
- **Scalability**: **Treenode Framework** suitable for solving simple problems such as menus, directories, parsing arithmetic expressions, as well as complex problems such as program optimization, image layout, multi-step decision making problems, or machine learning..
|
@@ -133,7 +134,7 @@ To get started quickly, you need to follow these steps:
|
|
133
134
|
|
134
135
|
- Simply install the package via `pip`:
|
135
136
|
```sh
|
136
|
-
pip install django-fast-
|
137
|
+
pip install django-fast-Treenode
|
137
138
|
```
|
138
139
|
- Once installed, add `'treenode'` to your `INSTALLED_APPS` in **settings.py**:
|
139
140
|
```python {title="settings.py"}
|
@@ -146,9 +147,9 @@ To get started quickly, you need to follow these steps:
|
|
146
147
|
|
147
148
|
- Open **models.py** and create your own tree class:
|
148
149
|
```
|
149
|
-
from
|
150
|
+
from Treenode.models import TreenodeModel
|
150
151
|
|
151
|
-
class MyTree(
|
152
|
+
class MyTree(TreenodeModel):
|
152
153
|
name = models.CharField(max_length=255)
|
153
154
|
display_field = "name"
|
154
155
|
```
|
@@ -156,11 +157,11 @@ To get started quickly, you need to follow these steps:
|
|
156
157
|
- Open **admin.py** and create a model for the admin panel
|
157
158
|
```
|
158
159
|
from django.contrib import admin
|
159
|
-
from
|
160
|
-
from .models import
|
160
|
+
from Treenode.admin import TreenodeModelAdmin
|
161
|
+
from .models import MyTree
|
161
162
|
|
162
|
-
@admin.register(
|
163
|
-
class
|
163
|
+
@admin.register(MyTree)
|
164
|
+
class MyTreeAdmin(TreenodeModelAdmin):
|
164
165
|
list_display = ("name",)
|
165
166
|
search_fields = ("name",)
|
166
167
|
```
|
@@ -175,25 +176,24 @@ To get started quickly, you need to follow these steps:
|
|
175
176
|
```sh
|
176
177
|
python manage.py runserver
|
177
178
|
```
|
178
|
-
|
179
179
|
Everything is ready, enjoy 🎉!
|
180
180
|
|
181
181
|
## Documentation
|
182
|
-
Full documentation is available at **[ReadTheDocs](https://django-fast-
|
182
|
+
Full documentation is available at **[ReadTheDocs](https://django-fast-Treenode.readthedocs.io/)**.
|
183
183
|
|
184
184
|
Quick access links:
|
185
|
-
* [Installation, configuration and fine tuning](https://django-fast-
|
186
|
-
* [Model Inheritance and Extensions](https://django-fast-
|
187
|
-
* [Working with Admin Classes](https://django-fast-
|
188
|
-
* [API Reference](https://django-fast-
|
189
|
-
* [Import & Export](https://django-fast-
|
190
|
-
* [Caching and working with cache](https://django-fast-
|
191
|
-
* [Migration and upgrade guide](https://django-fast-
|
185
|
+
* [Installation, configuration and fine tuning](https://django-fast-Treenode.readthedocs.io/installation/)
|
186
|
+
* [Model Inheritance and Extensions](https://django-fast-Treenode.readthedocs.io/models/)
|
187
|
+
* [Working with Admin Classes](https://django-fast-Treenode.readthedocs.io/admin/)
|
188
|
+
* [API Reference](https://django-fast-Treenode.readthedocs.io/api/)
|
189
|
+
* [Import & Export](https://django-fast-Treenode.readthedocs.io/import_export/)
|
190
|
+
* [Caching and working with cache](https://django-fast-Treenode.readthedocs.io/cache/)
|
191
|
+
* [Migration and upgrade guide](https://django-fast-Treenode.readthedocs.io/migration/)
|
192
192
|
|
193
193
|
Your wishes, objections, comments are welcome.
|
194
194
|
|
195
195
|
## License
|
196
|
-
Released under [MIT License](https://github.com/TimurKady/django-fast-
|
196
|
+
Released under [MIT License](https://github.com/TimurKady/django-fast-Treenode/blob/main/LICENSE).
|
197
197
|
|
198
198
|
## Credits
|
199
199
|
Thanks to everyone who contributed to the development and testing of this package, as well as the Django community for their inspiration and support.
|
@@ -194,7 +194,7 @@ All results were normalized relative to the best observed values. Lower values i
|
|
194
194
|
| Children | 🥇1,0 | 1,1 | 1,4 | 🥉1,0 | 🥈1,0 | 1,6 |
|
195
195
|
| Siblings | 🥇1,0 | 1,1 | 2,8 | 1,1 | 🥈1,0 | 1,1 |
|
196
196
|
| Family | 314,2 | 10.110,0 | 🥈236,2 | 🥉273,4 | 609,9 | 🥇1,0 |
|
197
|
-
| Re-reading | 338,4 | 8.416,7 | 🥉445,7 | 727,4 | 🥇1,0 |
|
197
|
+
| Re-reading | 338,4 | 8.416,7 | 🥉445,7 | 727,4 | 🥇1,0 | 🥈1,3 |
|
198
198
|
| Random | 253,8 | 1,1 | 274,5 | 🥇1,0 | 🥈1,0 | 🥉1,3 |
|
199
199
|
| Move | 🥇1,0 | 23,75 | 🥈1,6 | 🥈1,3 | 268,2 | 7,5 |
|
200
200
|
| Delete | 42,8 | 🥈3,63 | 🥈1,9 | 4,7 | 27,6 | 🥇1,0 |
|
@@ -1,4 +1,4 @@
|
|
1
|
-
#
|
1
|
+
# Treenode Framework
|
2
2
|
**A hybrid open-source framework for working with trees in Django**
|
3
3
|
|
4
4
|
Welcome to the **django-fast-treenode** documentation!
|
@@ -73,10 +73,10 @@ To get started quickly, you need to follow these steps:
|
|
73
73
|
```
|
74
74
|
from django.contrib import admin
|
75
75
|
from treenode.admin import TreeNodeModelAdmin
|
76
|
-
from .models import
|
76
|
+
from .models import MyTree
|
77
77
|
|
78
|
-
@admin.register(
|
79
|
-
class
|
78
|
+
@admin.register(MyTree)
|
79
|
+
class MyTreeAdmin(TreeNodeModelAdmin):
|
80
80
|
list_display = ("name",)
|
81
81
|
search_fields = ("name",)
|
82
82
|
```
|
@@ -147,14 +147,14 @@ The project is designed for long-term compatibility with future Django versions
|
|
147
147
|
|
148
148
|
All SQL queries are adapted through a universal compatibility layer, ensuring support for major databases without the need to rewrite SQL code.
|
149
149
|
|
150
|
-
| Database
|
151
|
-
|
152
|
-
| **PostgreSQL** | ≥
|
153
|
-
| **MySQL** | ≥ 8.0 | Partially tested |
|
154
|
-
| **MariaDB** | ≥ 10.
|
155
|
-
| **SQLite** | ≥ 3.
|
156
|
-
| **Oracle** | ≥ 12c
|
157
|
-
| **MS SQL Server** | ≥
|
150
|
+
| Database | Minimum Version | Status | Notes |
|
151
|
+
|:------------------|:------------------|:----------------|:-------------------|
|
152
|
+
| **PostgreSQL** | ≥ 10.0 | Full tested | Recommended ≥ 12 |
|
153
|
+
| **MySQL** | ≥ 8.0 | Partially tested | |
|
154
|
+
| **MariaDB** | ≥ 10.5 | Not tested | |
|
155
|
+
| **SQLite** | ≥ 3.35.0 | Partially tested | |
|
156
|
+
| **Oracle** | ≥ 12c R2 | Full tested | Recommended ≥ 19c |
|
157
|
+
| **MS SQL Server** | ≥ 2016 | Partially tested | |
|
158
158
|
|
159
159
|
|
160
160
|
The project is **ready for production use** across all modern versions of Django and major relational databases without manual SQL corrections.
|
@@ -178,7 +178,7 @@ def export_tree(node):
|
|
178
178
|
children = node.get_children()
|
179
179
|
return {
|
180
180
|
"id": node.id,
|
181
|
-
"
|
181
|
+
"parent": node.get_parent().id if node.get_parent() else None,
|
182
182
|
"name": node.name,
|
183
183
|
# Continue the list by inserting the required model fields
|
184
184
|
# Do not export the `children` field
|
@@ -192,7 +192,7 @@ with open("tree_data.json", "w") as f:
|
|
192
192
|
json.dump(data, f, indent=4)
|
193
193
|
```
|
194
194
|
|
195
|
-
This code exports your structure to `tree_data.json` file. JSON preserves the id →
|
195
|
+
This code exports your structure to `tree_data.json` file. JSON preserves the id → parent relationship, but without children.
|
196
196
|
|
197
197
|
Now clear the table:
|
198
198
|
```python
|
@@ -229,9 +229,9 @@ class Category(TreeNodeModel):
|
|
229
229
|
```
|
230
230
|
Be sure to add `treenode_display_field` as `django-fast-treenode` uses it to display nodes in the admin panel.
|
231
231
|
|
232
|
-
The `treenode_sort_field` attribute specifies the tree sorting order. The default value of this field is `None`. It will sort by the internal field `
|
232
|
+
The `treenode_sort_field` attribute specifies the tree sorting order. The default value of this field is `None`. It will sort by the internal field `priority`.
|
233
233
|
|
234
|
-
The `
|
234
|
+
The `priority` value will be generated automatically if not specified during import. It will either be set as nodes are inserted into the tree (in the order in which the nodes will appear in the imported data), or after they are inserted, depending on the results of sorting by the field specified in the `treenode_sort_field` attribute.
|
235
235
|
|
236
236
|
> Note: sorting functions are available for `django-tree-node` version 2.3 and higher.
|
237
237
|
|
@@ -20,13 +20,9 @@ The 3.x release series will focus on strengthening TreeNode Framework in terms o
|
|
20
20
|
|
21
21
|
Focus: enhance operational safety and optimize workflows for large-scale trees.
|
22
22
|
|
23
|
-
- **Safe Import Preview**:
|
23
|
+
- **Safe Import Preview**: Implement a staging layer for imports, allowing users to review and confirm imported data before committing changes.
|
24
24
|
|
25
|
-
|
26
|
-
|
27
|
-
- **Incremental Export**:
|
28
|
-
|
29
|
-
Support selective export of nodes modified after a specified date or revision marker.
|
25
|
+
- **Incremental Export**: Support selective export of nodes modified after a specified date or revision marker.
|
30
26
|
|
31
27
|
|
32
28
|
* **Version 3.3 — Soft Deletion Support**
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
4
4
|
|
5
5
|
[project]
|
6
6
|
name = "django-fast-treenode"
|
7
|
-
version = "3.0.
|
7
|
+
version = "3.0.3"
|
8
8
|
description = "Treenode Framework for supporting tree (hierarchical) data structure in Django projects"
|
9
9
|
readme = "README.md"
|
10
10
|
authors = [{ name = "Timur Kady", email = "timurkady@yandex.com" }]
|
@@ -43,3 +43,4 @@ Documentation = "https://django-fast-treenode.readthedocs.io/"
|
|
43
43
|
Source = "https://github.com/TimurKady/django-fast-treenode"
|
44
44
|
Issues = "https://github.com/TimurKady/django-fast-treenode/issues"
|
45
45
|
|
46
|
+
|
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
|
|
2
2
|
|
3
3
|
setup(
|
4
4
|
name='django-fast-treenode',
|
5
|
-
version='3.0.
|
5
|
+
version='3.0.3',
|
6
6
|
description='Treenode Framework for supporting tree (hierarchical) data structure in Django projects',
|
7
7
|
long_description=open('README.md', encoding='utf-8').read(),
|
8
8
|
long_description_content_type='text/markdown',
|
@@ -41,3 +41,4 @@ setup(
|
|
41
41
|
],
|
42
42
|
python_requires='>=3.9',
|
43
43
|
)
|
44
|
+
|
@@ -0,0 +1,99 @@
|
|
1
|
+
# tests/test_treenode.py
|
2
|
+
from django.test import TestCase
|
3
|
+
from django.db import transaction
|
4
|
+
from .models import TestModel
|
5
|
+
|
6
|
+
PATH_DIGITS = 3
|
7
|
+
|
8
|
+
|
9
|
+
def hex_path(parts):
|
10
|
+
"""Преобразуем массив индексов в нулепад-hex-строку."""
|
11
|
+
return ".".join(f"{n:0{PATH_DIGITS}X}" for n in parts)
|
12
|
+
|
13
|
+
|
14
|
+
class TreeNodeModelTests(TestCase):
|
15
|
+
"""Проверяем основные операции TreeNodeModel."""
|
16
|
+
|
17
|
+
@classmethod
|
18
|
+
def setUpTestData(cls):
|
19
|
+
"""
|
20
|
+
Создаём тестовое дерево один раз на весь класс.
|
21
|
+
Django сделает его снимок, и в каждом тесте база
|
22
|
+
будет возвращаться в это состояние автоматически.
|
23
|
+
"""
|
24
|
+
cls.root = TestModel.objects.create(name="root", priority=0)
|
25
|
+
cls.a = TestModel.objects.create(name="A", parent=cls.root, priority=1)
|
26
|
+
cls.b = TestModel.objects.create(name="B", parent=cls.root, priority=2)
|
27
|
+
cls.c = TestModel.objects.create(name="C", parent=cls.a, priority=1)
|
28
|
+
cls.d = TestModel.objects.create(name="D", parent=cls.a, priority=2)
|
29
|
+
|
30
|
+
_ = cls.a.get_order()
|
31
|
+
_ = cls.c.get_order()
|
32
|
+
|
33
|
+
# --- 1. Creating nodes -------------------------------------------------
|
34
|
+
|
35
|
+
def test_count_after_creation(self):
|
36
|
+
self.assertEqual(TestModel.objects.count(), 5)
|
37
|
+
|
38
|
+
# --- 2. _path and _depth --------------------------------------------------
|
39
|
+
|
40
|
+
def test_path_and_depth_saved(self):
|
41
|
+
with self.subTest("Depth values"):
|
42
|
+
self.assertEqual(self.a.get_depth(), 1)
|
43
|
+
self.assertEqual(self.c.get_depth(), 2)
|
44
|
+
|
45
|
+
with self.subTest("Path format"):
|
46
|
+
self.assertIn(".", self.a.get_order())
|
47
|
+
self.assertIn(".", self.c.get_order())
|
48
|
+
|
49
|
+
# --- 3. Ancestors and Descendants ------------------------------------------------
|
50
|
+
|
51
|
+
def test_ancestors_and_descendants(self):
|
52
|
+
TestModel.tasks.add("update", None)
|
53
|
+
TestModel.tasks.run()
|
54
|
+
|
55
|
+
ancestors = set(
|
56
|
+
self.c.get_ancestors_queryset().values_list("pk", flat=True)
|
57
|
+
)
|
58
|
+
expected_anc = {self.root.pk, self.a.pk, self.c.pk}
|
59
|
+
self.assertEqual(ancestors, expected_anc)
|
60
|
+
|
61
|
+
descendants = set(
|
62
|
+
self.root.get_descendants_queryset(include_self=True)
|
63
|
+
.values_list("pk", flat=True)
|
64
|
+
)
|
65
|
+
expected_desc = {
|
66
|
+
self.root.pk, self.a.pk, self.b.pk, self.c.pk, self.d.pk
|
67
|
+
}
|
68
|
+
|
69
|
+
test = descendants == expected_desc
|
70
|
+
|
71
|
+
self.assertEqual(test, True)
|
72
|
+
|
73
|
+
# --- 4. Moving a node ------------------------------------------------
|
74
|
+
|
75
|
+
def test_move_node(self):
|
76
|
+
# перемещаем c под b и проверяем
|
77
|
+
with transaction.atomic():
|
78
|
+
self.c.move_to(self.b)
|
79
|
+
|
80
|
+
self.c.refresh_from_db()
|
81
|
+
self.assertEqual(self.c.parent_id, self.b.pk)
|
82
|
+
self.assertEqual(self.c.get_depth(), self.b.get_depth() + 1)
|
83
|
+
self.assertTrue(
|
84
|
+
self.c.get_order().startswith(f"{self.b.get_order()}.")
|
85
|
+
)
|
86
|
+
self.assertEqual(self.c.get_order().count("."), self.c.get_depth())
|
87
|
+
|
88
|
+
# --- 5. Removing a node ---------------------------------------------------
|
89
|
+
|
90
|
+
def test_delete_subtree(self):
|
91
|
+
self.a.delete(cascade=False)
|
92
|
+
|
93
|
+
tree_data = TestModel.get_tree_json()
|
94
|
+
|
95
|
+
self.root.check_tree_integrity()
|
96
|
+
qs = TestModel.objects.filter(pk__in=[self.a.pk, self.c.pk]).all()
|
97
|
+
|
98
|
+
self.assertFalse(TestModel.objects.filter(pk=self.a.pk).exists())
|
99
|
+
self.assertTrue(TestModel.objects.filter(pk=self.c.pk).exists())
|