django-fast-treenode 2.1.0__py3-none-any.whl → 2.1.1__py3-none-any.whl
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-2.1.0.dist-info → django_fast_treenode-2.1.1.dist-info}/METADATA +10 -13
- {django_fast_treenode-2.1.0.dist-info → django_fast_treenode-2.1.1.dist-info}/RECORD +5 -16
- treenode/docs/.gitignore +0 -0
- treenode/docs/about.md +0 -36
- treenode/docs/admin.md +0 -104
- treenode/docs/api.md +0 -739
- treenode/docs/cache.md +0 -187
- treenode/docs/import_export.md +0 -35
- treenode/docs/index.md +0 -30
- treenode/docs/installation.md +0 -74
- treenode/docs/migration.md +0 -145
- treenode/docs/models.md +0 -128
- treenode/docs/roadmap.md +0 -45
- {django_fast_treenode-2.1.0.dist-info → django_fast_treenode-2.1.1.dist-info}/LICENSE +0 -0
- {django_fast_treenode-2.1.0.dist-info → django_fast_treenode-2.1.1.dist-info}/WHEEL +0 -0
- {django_fast_treenode-2.1.0.dist-info → django_fast_treenode-2.1.1.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.2
|
2
2
|
Name: django-fast-treenode
|
3
|
-
Version: 2.1.
|
3
|
+
Version: 2.1.1
|
4
4
|
Summary: Application for supporting tree (hierarchical) data structure in Django projects
|
5
5
|
Home-page: https://github.com/TimurKady/django-fast-treenode
|
6
6
|
Author: Timur Kady
|
@@ -28,7 +28,7 @@ License: MIT License
|
|
28
28
|
SOFTWARE.
|
29
29
|
|
30
30
|
Project-URL: Homepage, https://github.com/TimurKady/django-fast-treenode
|
31
|
-
Project-URL: Documentation, https://
|
31
|
+
Project-URL: Documentation, https://django-fast-treenode.readthedocs.io/latest/
|
32
32
|
Project-URL: Source, https://github.com/TimurKady/django-fast-treenode
|
33
33
|
Project-URL: Issues, https://github.com/TimurKady/django-fast-treenode/issues
|
34
34
|
Classifier: Development Status :: 5 - Production/Stable
|
@@ -60,9 +60,6 @@ Requires-Dist: openpyxl; extra == "import-export"
|
|
60
60
|
Requires-Dist: pyyaml; extra == "import-export"
|
61
61
|
Requires-Dist: xlsxwriter; extra == "import-export"
|
62
62
|
|
63
|
-
|
64
|
-
# ⚠️ Version 2.1.0 - betta.
|
65
|
-
|
66
63
|
# Django-fast-treenode
|
67
64
|
**Combining Adjacency List and Closure Table for Optimal Performance**
|
68
65
|
|
@@ -139,16 +136,16 @@ python manage.py migrate
|
|
139
136
|
```
|
140
137
|
|
141
138
|
## Documentation
|
142
|
-
Full documentation is available at [this link](
|
139
|
+
Full documentation is available at [this link](https://django-fast-treenode.readthedocs.io/latest/).
|
143
140
|
|
144
141
|
Quick access links:
|
145
|
-
* [Installation, configuration and fine tuning](
|
146
|
-
* [Model Inheritance and Extensions](
|
147
|
-
* [Working with Admin Classes](
|
148
|
-
* [API Reference](
|
149
|
-
* [Import & Export](
|
150
|
-
* [Caching and working with cache](
|
151
|
-
* [Migration and upgrade guide](
|
142
|
+
* [Installation, configuration and fine tuning](https://django-fast-treenode.readthedocs.io/latest/installation/)
|
143
|
+
* [Model Inheritance and Extensions](https://django-fast-treenode.readthedocs.io/latest/models/)
|
144
|
+
* [Working with Admin Classes](https://django-fast-treenode.readthedocs.io/latest/admin/)
|
145
|
+
* [API Reference](https://django-fast-treenode.readthedocs.io/latest/api/)
|
146
|
+
* [Import & Export](https://django-fast-treenode.readthedocs.io/latest/import_export/)
|
147
|
+
* [Caching and working with cache](https://django-fast-treenode.readthedocs.io/latest/cache/)
|
148
|
+
* [Migration and upgrade guide](https://django-fast-treenode.readthedocs.io/latest/migration/)
|
152
149
|
|
153
150
|
Your wishes, objections, comments are welcome.
|
154
151
|
|
@@ -11,17 +11,6 @@ treenode/admin/__init__.py,sha256=TdlPIyRW8i9qTVqGLmLWiBw4DyoGHUYZErE6rCyGOPE,11
|
|
11
11
|
treenode/admin/admin.py,sha256=6H3N2Dg6l-MrFwIcyKR5YENg0cEo-I4uKCP9MuhHkqo,10580
|
12
12
|
treenode/admin/changelist.py,sha256=YZm3zNniX75CgLjnbHpVr0OIP91halDEBHmrcS8m5Og,2128
|
13
13
|
treenode/admin/mixins.py,sha256=-dVZwEjKsfRzMkBe87dkI0SZ9MH45YE_o39SIhSJWy4,11194
|
14
|
-
treenode/docs/.gitignore,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
15
|
-
treenode/docs/about.md,sha256=x0RnV3UiTn-Ii0nBpTPgQmm6Al_DDwtl72TUC2oH_-0,3532
|
16
|
-
treenode/docs/admin.md,sha256=uA3esa2AF3epcXtfEN-JUoUXojw34PAGg-g3w9aqY8I,4653
|
17
|
-
treenode/docs/api.md,sha256=xDq9BDIhg7qOOZa88fF2WhHL8Wr77dYLmLnZ2fctF8I,23524
|
18
|
-
treenode/docs/cache.md,sha256=mX4P0a4ndyLZCEDKEXPBEcd8LSWqvEy_HdYIHgmnf8g,8323
|
19
|
-
treenode/docs/import_export.md,sha256=sbI1iR-eI54obTaIeR5xDhjn8FAy3dJ0aR4rfbCRcyU,2134
|
20
|
-
treenode/docs/index.md,sha256=wXq_8AA9RooIG_6V_Yq5KPgrxyOKkc84sq-lwa-FQDk,1140
|
21
|
-
treenode/docs/installation.md,sha256=w_ImbNgdt0Ot-z2ERApkRcBz1TdXloOFkNzU3EJBxeA,2512
|
22
|
-
treenode/docs/migration.md,sha256=eFZO_DWJA8-015hD0he7_HzxgMnbOv192M-9Zf1uLcQ,6581
|
23
|
-
treenode/docs/models.md,sha256=PxLHVvQDsH-IsD3pwilTtjUeB8hROYWNf3jdbHjhESY,5781
|
24
|
-
treenode/docs/roadmap.md,sha256=T3aB3LfqhfXdpc9phTA4oPlQriKTjfuoaMBvvMcHa90,3336
|
25
14
|
treenode/managers/__init__.py,sha256=EG_tj9P1Hama3kaqMfHck4lfzUWoPaJJVOXe3qaKMUo,585
|
26
15
|
treenode/managers/adjacency.py,sha256=NVN8dq5z7gIh90yqW2uxV7MokmUfXTOT7crqMDyMaH0,7889
|
27
16
|
treenode/managers/closure.py,sha256=PcScdJJUnLcKe8Y1wqROYPsRtAnBMUO4xn5sILk9AIM,10638
|
@@ -68,8 +57,8 @@ treenode/utils/db.py,sha256=36q4OckKmEd6uHTbMTxdKpV9nOIZ55DAantRWR9bxWg,4297
|
|
68
57
|
treenode/utils/exporter.py,sha256=mV6Gch7XfW8f_1x3WqWgtV0qekMLdo-_n9gz6GJjXjw,7259
|
69
58
|
treenode/utils/importer.py,sha256=Hvirbd6NyZ2MHa56_jOrUF3kYFeby1DbSLR3mhHy-9s,12891
|
70
59
|
treenode/utils/radix.py,sha256=zHpOuDxsebiv9Gza6snNhAtBKiex6CDrAVRtB6esaWo,1642
|
71
|
-
django_fast_treenode-2.1.
|
72
|
-
django_fast_treenode-2.1.
|
73
|
-
django_fast_treenode-2.1.
|
74
|
-
django_fast_treenode-2.1.
|
75
|
-
django_fast_treenode-2.1.
|
60
|
+
django_fast_treenode-2.1.1.dist-info/LICENSE,sha256=T0evsb7y-63fg18ovdNSx3wwWWRwyluQvN9J4zFSvfE,1093
|
61
|
+
django_fast_treenode-2.1.1.dist-info/METADATA,sha256=E1ThWhY4yy_h8_28imc4CYkd4kR7e9aCvtvpa6Pyncs,7620
|
62
|
+
django_fast_treenode-2.1.1.dist-info/WHEEL,sha256=jB7zZ3N9hIM9adW7qlTAyycLYW9npaWKLRzaoVcLKcM,91
|
63
|
+
django_fast_treenode-2.1.1.dist-info/top_level.txt,sha256=fmgxHbXyx1O2MPi_9kjx8aL9L-8TmV0gre4Go8XgqFk,9
|
64
|
+
django_fast_treenode-2.1.1.dist-info/RECORD,,
|
treenode/docs/.gitignore
DELETED
File without changes
|
treenode/docs/about.md
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
## About the project
|
2
|
-
### The Debut Idea
|
3
|
-
The idea of this package belongs to **[Fabio Caccamo](https://github.com/fabiocaccamo)**. His idea was to use the **Adjacency List** method to store the data tree. The most probable and time-consuming requests are calculated in advance and stored in the database. Also, most requests are cached. As a result, query processing is carried out in one call to the database or without it at all.
|
4
|
-
|
5
|
-
The original application **[django-treenode](https://github.com/fabiocaccamo/django-treenode)** has significant advantages over other analogues, and indeed, is one of the best implementations of support for hierarchical structures for Django.
|
6
|
-
|
7
|
-
However, this application has a number of undeniable shortcomings:
|
8
|
-
* the selected pre-calculations scheme entails high costs for adding a new element;
|
9
|
-
* inserting new elements uses signals, which leads to failures when using bulk-operations;
|
10
|
-
* the problem of ordering elements by priority inside the parent node has not been resolved.
|
11
|
-
|
12
|
-
That is, an excellent debut idea, in my humble opinion, should have been improved.
|
13
|
-
|
14
|
-
### The Development of the Idea
|
15
|
-
My idea was to solve these problems by combining the **Adjacency List** with the **Closure Table**. Main advantages:
|
16
|
-
* the Closure Model is generated automatically;
|
17
|
-
* maintained compatibility with the original package at the level of documented functions;
|
18
|
-
* most requests are satisfied in one call to the database;
|
19
|
-
* inserting a new element takes two calls to the database without signals usage;
|
20
|
-
* bulk-operations are supported;
|
21
|
-
* the cost of creating a new dependency is reduced many times;
|
22
|
-
* useful functionality added for some methods (e.g. the `include_self=False` and `depth` parameters has been added to functions that return lists/querysets);
|
23
|
-
* additionally, the package includes a tree view widget for the `tn_parent` field in the change form.
|
24
|
-
|
25
|
-
Of course, at large levels of nesting, the use of the Closure Table leads to an increase in resource costs. However, the combined approach still outperforms both the original application and other available Django solutions in terms of performance, especially in large trees with over 100k nodes.
|
26
|
-
|
27
|
-
### The Theory
|
28
|
-
You can get a basic understanding of what is a **Closure Table** from:
|
29
|
-
* [presentation](https://www.slideshare.net/billkarwin/models-for-hierarchical-data) by **Bill Karwin**;
|
30
|
-
* [article](https://dirtsimple.org/2010/11/simplest-way-to-do-tree-based-queries.html) by blogger **Dirt Simple**;
|
31
|
-
* [article](https://towardsdatascience.com/closure-table-pattern-to-model-hierarchies-in-nosql-c1be6a87e05b) by **Andriy Zabavskyy**.
|
32
|
-
|
33
|
-
You can easily find additional information on your own on the Internet.
|
34
|
-
|
35
|
-
### Our days
|
36
|
-
Over the course of development, the package has undergone significant improvements, with a strong emphasis on performance optimization, database efficiency, and seamless integration with Django’s admin interface. The introduction of a hybrid model combining **Adjacency List** and **Closure Table** has substantially reduced query overhead, improved scalability, and enhanced flexibility when managing hierarchical data. These advancements have made the package not only a powerful but also a practical solution for working with large tree structures. Moving forward, the project will continue to evolve, focusing on refining caching mechanisms, expanding compatibility with Django’s ecosystem, and introducing further optimizations to ensure maximum efficiency and ease of use.
|
treenode/docs/admin.md
DELETED
@@ -1,104 +0,0 @@
|
|
1
|
-
## Working with Admin Classes
|
2
|
-
|
3
|
-
### Using `TreeNodeModelAdmin`
|
4
|
-
The easiest way to integrate tree structures into Django’s admin panel is by inheriting from `TreeNodeModelAdmin`. This base class provides all the necessary functionality for managing hierarchical data.
|
5
|
-
|
6
|
-
##### admin.py:
|
7
|
-
```python
|
8
|
-
from django.contrib import admin
|
9
|
-
from treenode.admin import TreeNodeModelAdmin
|
10
|
-
|
11
|
-
from .models import Category
|
12
|
-
|
13
|
-
@admin.register(Category)
|
14
|
-
class CategoryAdmin(TreeNodeModelAdmin):
|
15
|
-
|
16
|
-
# Set the display mode: 'accordion', 'breadcrumbs', or 'indentation'
|
17
|
-
treenode_display_mode = TreeNodeModelAdmin.TREENODE_DISPLAY_MODE_ACCORDION
|
18
|
-
# treenode_display_mode = TreeNodeModelAdmin.TREENODE_DISPLAY_MODE_BREADCRUMBS
|
19
|
-
# treenode_display_mode = TreeNodeModelAdmin.TREENODE_DISPLAY_MODE_INDENTATION
|
20
|
-
|
21
|
-
list_display = ("name",)
|
22
|
-
search_fields = ("name",)
|
23
|
-
```
|
24
|
-
|
25
|
-
The tree structure in the admin panel **loads dynamically as nodes are expanded**. This allows handling **large datasets** efficiently, preventing performance issues.
|
26
|
-
|
27
|
-
You can choose from three display modes:
|
28
|
-
- **`TREENODE_DISPLAY_MODE_ACCORDION` (default)**
|
29
|
-
Expands/collapses nodes dynamically.
|
30
|
-
- **`TREENODE_DISPLAY_MODE_BREADCRUMBS`**
|
31
|
-
Displays the tree as a sequence of **breadcrumbs**, making it easy to navigate.
|
32
|
-
- **`TREENODE_DISPLAY_MODE_INDENTATION`**
|
33
|
-
Uses a **long dash** (`———`) to indicate nesting levels, providing a simple visual structure.
|
34
|
-
|
35
|
-
The accordion mode is **always active**, and the setting only affects how nodes are displayed.
|
36
|
-
|
37
|
-
**Why Dynamic Loading**: Traditional pagination does not work well for **deep hierarchical trees**, as collapsed trees may contain a **huge number of nodes**, which is in the hundreds of thousands. The dynamic approach allows efficient loading, reducing database load while keeping large trees manageable.
|
38
|
-
|
39
|
-
#### Search Functionality
|
40
|
-
The search bar helps quickly locate nodes within large trees. As you type, **an AJAX request retrieves up to 20 results** based on relevance. If you don’t find the desired node, keep typing to refine the search until fewer than 20 results remain.
|
41
|
-
|
42
|
-
### Working with Forms
|
43
|
-
|
44
|
-
#### Using TreeNodeForm
|
45
|
-
If you need to customize forms for tree-based models, inherit from `TreeNodeForm`. It provides:
|
46
|
-
- A **custom tree widget** for selecting parent nodes.
|
47
|
-
- Automatic **exclusion of self and descendants** from the parent selection to prevent circular references.
|
48
|
-
|
49
|
-
##### `forms.py`:
|
50
|
-
```python
|
51
|
-
from treenode.forms import TreeNodeForm
|
52
|
-
from .models import Category
|
53
|
-
|
54
|
-
class CategoryForm(TreeNodeForm):
|
55
|
-
"""Form for Category model with hierarchical selection."""
|
56
|
-
|
57
|
-
class Meta(TreeNodeForm.Meta):
|
58
|
-
model = Category
|
59
|
-
```
|
60
|
-
|
61
|
-
Key Considerations:
|
62
|
-
- This form automatically ensures that **a node cannot be its own parent**.
|
63
|
-
- It uses **`TreeWidget`**, a custom hierarchical dropdown for selecting parent nodes.
|
64
|
-
- If you need a form for another tree-based model, use the **dynamic factory method**:
|
65
|
-
|
66
|
-
```python
|
67
|
-
CategoryForm = TreeNodeForm.factory(Category)
|
68
|
-
```
|
69
|
-
|
70
|
-
This method ensures that the form correctly associates with different tree models dynamically.
|
71
|
-
|
72
|
-
|
73
|
-
### Using TreeWidget Widget
|
74
|
-
|
75
|
-
#### The TreeWidget Class
|
76
|
-
The `TreeWidget` class is a **custom Select2-like widget** that enables hierarchical selection in forms. While it is used inside the Django admin panel by default, it can **also be used in regular forms** outside the admin panel.
|
77
|
-
|
78
|
-
##### `widgets.py`
|
79
|
-
|
80
|
-
```python
|
81
|
-
from django import forms
|
82
|
-
from treenode.widgets import TreeWidget
|
83
|
-
from .models import Category
|
84
|
-
|
85
|
-
class CategorySelectionForm(forms.Form):
|
86
|
-
parent = forms.ModelChoiceField(
|
87
|
-
queryset=Category.objects.all(),
|
88
|
-
widget=TreeWidget(),
|
89
|
-
required=False
|
90
|
-
)
|
91
|
-
```
|
92
|
-
|
93
|
-
Important Notes:
|
94
|
-
- **Requires jQuery**: The widget relies on AJAX requests, so ensure jQuery is available when using it outside Django’s admin.
|
95
|
-
- **Dynamically Fetches Data**: It loads the tree structure asynchronously, preventing performance issues with large datasets.
|
96
|
-
- **Customizable Data Source**: The `data-url` attribute can be adjusted to fetch tree data from a custom endpoint.
|
97
|
-
|
98
|
-
If you plan to use this widget in non-admin templates, make sure the necessary **JavaScript and CSS files** are included:
|
99
|
-
```html
|
100
|
-
<link rel="stylesheet" href="/static/treenode/tree_widget.css">
|
101
|
-
<script src="/static/treenode/js/tree_widget.js"></script>
|
102
|
-
```
|
103
|
-
|
104
|
-
By following these guidelines, you can seamlessly integrate `TreeNodeModelAdmin`, `TreeNodeForm`, and `TreeWidget` into your Django project, ensuring efficient management of hierarchical data.
|