django-fast-treenode 1.1.3__py3-none-any.whl → 2.0.0__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- {django_fast_treenode-1.1.3.dist-info → django_fast_treenode-2.0.0.dist-info}/METADATA +156 -46
- django_fast_treenode-2.0.0.dist-info/RECORD +41 -0
- {django_fast_treenode-1.1.3.dist-info → django_fast_treenode-2.0.0.dist-info}/WHEEL +1 -1
- treenode/__init__.py +0 -7
- treenode/admin.py +327 -82
- treenode/apps.py +20 -3
- treenode/cache.py +231 -0
- treenode/docs/Documentation +130 -54
- treenode/forms.py +75 -19
- treenode/managers.py +260 -48
- treenode/models/__init__.py +7 -0
- treenode/models/classproperty.py +24 -0
- treenode/models/closure.py +168 -0
- treenode/models/factory.py +71 -0
- treenode/models/proxy.py +650 -0
- treenode/static/treenode/css/tree_widget.css +62 -0
- treenode/static/treenode/css/treenode_admin.css +106 -0
- treenode/static/treenode/js/tree_widget.js +161 -0
- treenode/static/treenode/js/treenode_admin.js +171 -0
- treenode/templates/admin/export_success.html +26 -0
- treenode/templates/admin/tree_node_changelist.html +11 -0
- treenode/templates/admin/tree_node_export.html +27 -0
- treenode/templates/admin/tree_node_import.html +27 -0
- treenode/templates/widgets/tree_widget.css +23 -0
- treenode/templates/widgets/tree_widget.html +21 -0
- treenode/urls.py +34 -0
- treenode/utils/__init__.py +4 -0
- treenode/utils/base36.py +35 -0
- treenode/utils/exporter.py +141 -0
- treenode/utils/importer.py +296 -0
- treenode/version.py +11 -1
- treenode/views.py +102 -2
- treenode/widgets.py +49 -27
- django_fast_treenode-1.1.3.dist-info/RECORD +0 -33
- treenode/compat.py +0 -8
- treenode/factory.py +0 -68
- treenode/models.py +0 -668
- treenode/static/select2tree/.gitkeep +0 -1
- treenode/static/select2tree/select2tree.css +0 -176
- treenode/static/select2tree/select2tree.js +0 -181
- treenode/static/treenode/css/treenode.css +0 -85
- treenode/static/treenode/js/treenode.js +0 -201
- treenode/templates/widgets/.gitkeep +0 -1
- treenode/templates/widgets/attrs.html +0 -7
- treenode/templates/widgets/options.html +0 -1
- treenode/templates/widgets/select2tree.html +0 -22
- treenode/tests.py +0 -3
- {django_fast_treenode-1.1.3.dist-info → django_fast_treenode-2.0.0.dist-info}/LICENSE +0 -0
- {django_fast_treenode-1.1.3.dist-info → django_fast_treenode-2.0.0.dist-info}/top_level.txt +0 -0
- /treenode/{docs → templates/admin}/.gitkeep +0 -0
@@ -1,28 +1,44 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.2
|
2
2
|
Name: django-fast-treenode
|
3
|
-
Version:
|
3
|
+
Version: 2.0.0
|
4
4
|
Summary: Application for supporting tree (hierarchical) data structure in Django projects
|
5
5
|
Home-page: https://github.com/TimurKady/fast-treenode
|
6
6
|
Author: Timur Kady
|
7
|
-
Author-email:
|
8
|
-
License: MIT
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
7
|
+
Author-email: Timur Kady <kaduevtr@gmail.com>
|
8
|
+
License: MIT License
|
9
|
+
|
10
|
+
Copyright (c) 2020-2023 Timur Kady
|
11
|
+
|
12
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
13
|
+
of this software and associated documentation files (the "Software"), to deal
|
14
|
+
in the Software without restriction, including without limitation the rights
|
15
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
16
|
+
copies of the Software, and to permit persons to whom the Software is
|
17
|
+
furnished to do so, subject to the following conditions:
|
18
|
+
|
19
|
+
The above copyright notice and this permission notice shall be included in all
|
20
|
+
copies or substantial portions of the Software.
|
21
|
+
|
22
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
23
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
24
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
25
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
26
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
27
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
28
|
+
SOFTWARE.
|
29
|
+
Project-URL: Homepage, https://github.com/TimurKady/django-fast-treenode
|
30
|
+
Project-URL: Documentation, https://github.com/TimurKady/django-fast-treenode#readme
|
31
|
+
Project-URL: Source, https://github.com/TimurKady/django-fast-treenode
|
32
|
+
Project-URL: Issues, https://github.com/TimurKady/django-fast-treenode/issues
|
33
|
+
Requires-Python: >=3.9
|
23
34
|
Description-Content-Type: text/markdown
|
24
35
|
License-File: LICENSE
|
25
|
-
Requires-Dist: Django
|
36
|
+
Requires-Dist: Django<5.0,>=3.2
|
37
|
+
Requires-Dist: pympler>=1.0
|
38
|
+
Provides-Extra: import-export
|
39
|
+
Requires-Dist: openpyxl; extra == "import-export"
|
40
|
+
Requires-Dist: pyyaml; extra == "import-export"
|
41
|
+
Requires-Dist: pandas; extra == "import-export"
|
26
42
|
|
27
43
|
# Django-fast-treenode
|
28
44
|
__Combination of Adjacency List and Closure Table__
|
@@ -76,8 +92,7 @@ You can easily find additional information on your own on the Internet.
|
|
76
92
|
4. Make your model-admin inherit from ```treenode.admin.TreeNodeModelAdmin``` (described below)
|
77
93
|
5. Run python manage.py makemigrations and ```python manage.py migrate```
|
78
94
|
|
79
|
-
|
80
|
-
It will automatically build a new and complete Closure Table for your tree.
|
95
|
+
For more information on migrating from the **django-treenode** package and upgrading to version 2.0, see [below](#migration-guide).
|
81
96
|
|
82
97
|
## Configuration
|
83
98
|
### `models.py`
|
@@ -143,6 +158,8 @@ CACHES = {
|
|
143
158
|
},
|
144
159
|
"treenode": {
|
145
160
|
"BACKEND": "django.core.cache.backends.locmem.LocMemCache",
|
161
|
+
"KEY_PREFIX": "", # This is important!
|
162
|
+
"VERSION": None, # This is important!
|
146
163
|
},
|
147
164
|
}
|
148
165
|
```
|
@@ -150,15 +167,42 @@ CACHES = {
|
|
150
167
|
|
151
168
|
```
|
152
169
|
class YoursForm(TreeNodeForm):
|
153
|
-
|
154
|
-
class Meta:
|
155
|
-
widgets = {
|
156
|
-
'tn_parent': TreeWidget(attrs={'style': 'min-width:400px'}),
|
157
|
-
}
|
170
|
+
# Your code is here
|
158
171
|
```
|
159
172
|
|
160
|
-
##
|
173
|
+
## Updating to django-fast-treenode 2.X
|
174
|
+
### Overview
|
175
|
+
If you are upgrading from a previous version, you need to follow these steps to ensure compatibility and proper functionality.
|
176
|
+
|
177
|
+
### Update Process
|
178
|
+
1. **Upgrade the package**
|
179
|
+
Run the following command to install the latest version:
|
180
|
+
|
181
|
+
```bash
|
182
|
+
pip install --upgrade django-fast-treenode
|
183
|
+
```
|
184
|
+
|
185
|
+
2. **Apply database migrations**
|
186
|
+
After upgrading, you need to apply the necessary database migrations:
|
187
|
+
|
188
|
+
```bash
|
189
|
+
python manage.py makemigrations
|
190
|
+
python manage.py migrate
|
191
|
+
```
|
192
|
+
|
193
|
+
3. **Restart the application**
|
194
|
+
Finally, restart your Django application to apply all changes:
|
195
|
+
|
196
|
+
```bash
|
197
|
+
python manage.py runserver
|
198
|
+
```
|
161
199
|
|
200
|
+
**Important Notes**: Failing to apply migrations (`migrate`) after upgrading may lead to errors when interacting with tree nodes.
|
201
|
+
|
202
|
+
By following these steps, you will ensure a smooth transition to the latest version of django-fast-treenode without data inconsistencies.
|
203
|
+
|
204
|
+
|
205
|
+
## Usage
|
162
206
|
### Methods/Properties
|
163
207
|
|
164
208
|
- [`delete`](#delete)
|
@@ -213,11 +257,17 @@ class YoursForm(TreeNodeForm):
|
|
213
257
|
- [`update_tree`](#update_tree)
|
214
258
|
|
215
259
|
#### `delete`
|
216
|
-
**Delete a node**
|
217
|
-
|
260
|
+
**Delete a node** provides two deletion strategies:
|
261
|
+
- **Cascade Delete (`cascade=True`)**: Removes the node along with all its descendants.
|
262
|
+
- **Reparenting (`cascade=False`)**: Moves the children of the deleted node up one level in the hierarchy before removing the node itself.
|
263
|
+
|
218
264
|
```python
|
219
|
-
|
265
|
+
node.delete(cascade=True) # Deletes node and all its descendants
|
266
|
+
node.delete(cascade=False) # Moves children up and then deletes the node
|
220
267
|
```
|
268
|
+
This ensures greater flexibility in managing tree structures while preventing orphaned nodes.
|
269
|
+
|
270
|
+
---
|
221
271
|
|
222
272
|
#### `delete_tree`
|
223
273
|
**Delete the whole tree** for the current node class:
|
@@ -339,6 +389,8 @@ obj.get_descendants_tree()
|
|
339
389
|
obj.descendants_tree
|
340
390
|
```
|
341
391
|
|
392
|
+
**Important**: In future projects, avoid using `get_descendants_tree()`. It will be removed in the next version.
|
393
|
+
|
342
394
|
#### `get_descendants_tree_display`
|
343
395
|
Get a **multiline** `string` representing the **model tree**:
|
344
396
|
```python
|
@@ -347,6 +399,8 @@ obj.get_descendants_tree_display(include_self=False, depth=None)
|
|
347
399
|
obj.descendants_tree_display
|
348
400
|
```
|
349
401
|
|
402
|
+
**Important**: In future projects, avoid using `get_descendants_tree_display()`. It will be removed in the next version.
|
403
|
+
|
350
404
|
#### `get_first_child`
|
351
405
|
Get the **first child node**:
|
352
406
|
```python
|
@@ -570,27 +624,83 @@ obj.is_sibling_of(target_obj)
|
|
570
624
|
```python
|
571
625
|
cls.update_tree()
|
572
626
|
```
|
627
|
+
## **Cache Management**
|
628
|
+
### **Overview**
|
629
|
+
In v2.0, the caching mechanism has been improved to prevent excessive memory usage when multiple models inherit from `TreeNode`. The new system introduces **FIFO (First-In-First-Out) cache eviction**, with plans to test and integrate more advanced algorithms in future releases.
|
630
|
+
|
631
|
+
### **Key Features**
|
632
|
+
**Global Cache Limit**: The setting `TREENODE_CACHE_LIMIT` defines the maximum cache size (in MB) for all models inheriting from `TreeNode`. Default is **100MB** if not explicitly set in `settings.py`.
|
633
|
+
**settings.py**
|
634
|
+
``` python
|
635
|
+
TREENODE_CACHE_LIMIT = 100
|
636
|
+
```
|
637
|
+
**Automatic Management**: In most cases, users don’t need to manually manage cache operations.
|
638
|
+
**Manual Cache Clearing**:
|
639
|
+
- **Clear cache for a single model**: Use `clear_cache()` at the model level:
|
640
|
+
```python
|
641
|
+
MyTreeNodeModel.clear_cache()
|
642
|
+
```
|
643
|
+
- **Clear cache for all models**: Use the global `treenode_cache.clear()` method:
|
644
|
+
```python
|
645
|
+
from treenode.cache import treenode_cache
|
646
|
+
treenode_cache.clear()
|
647
|
+
```
|
648
|
+
|
649
|
+
## **Export and Import Functionality**
|
650
|
+
### **Overview**
|
651
|
+
TreeNode v2.0 includes **built-in export and import features** for easier data migration. Supported Formats: `csv`, `json`, `xlsx`, `yaml`, `tsv`
|
652
|
+
### Installation for Import/Export Features
|
653
|
+
By default, import/export functionality is **not included** to keep the package lightweight. If you need these features, install the package with:
|
654
|
+
```bash
|
655
|
+
pip install django-fast-treenode[import_export]
|
656
|
+
```
|
657
|
+
Once installed, **import/export buttons will appear** in the Django admin interface.
|
658
|
+
### **Important Considerations**
|
659
|
+
Exporting objects with M2M fields may lead to serialization issues. Some formats (e.g., CSV) do not natively support many-to-many relationships. If you encounter errors, consider exporting data in `json` or `yaml` format, which better handle nested structures.
|
660
|
+
|
661
|
+
## Migration Guide
|
662
|
+
#### Switching from `django-treenode`
|
663
|
+
The migration process from `django-treenode` is fully automated. No manual steps are required. Upon upgrading, the necessary data structures will be checked and updated automatically. In exceptional cases, you can call the update code `cls.update_tree()` manually.
|
664
|
+
|
665
|
+
|
666
|
+
#### Upgrading to `django-fast-treenode` 2.0
|
667
|
+
To upgrade to version 2.0, simply run:
|
668
|
+
```bash
|
669
|
+
pip install --upgrade django-fast-treenode
|
670
|
+
```
|
671
|
+
or
|
672
|
+
```bash
|
673
|
+
pip install django-fast-treenode[import_export]
|
674
|
+
```
|
675
|
+
After upgrading, ensure that your database schema is up to date by running:
|
676
|
+
```bash
|
677
|
+
python manage.py makemigrations
|
678
|
+
python manage.py migrate
|
679
|
+
```
|
680
|
+
This will apply any necessary database changes automatically.
|
573
681
|
|
574
|
-
##
|
575
|
-
|
682
|
+
## To do
|
683
|
+
These improvements aim to enhance usability, performance, and maintainability for all users of `django-fast-treenode`:
|
684
|
+
* **Cache Algorithm Optimization**: Testing and integrating more advanced cache eviction strategies.
|
685
|
+
* **Drag-and-Drop UI Enhancements**: Adding intuitive drag-and-drop functionality for tree node management.
|
686
|
+
* to be happy, to don't worry, until die.
|
576
687
|
|
577
|
-
|
578
|
-
The provided code is already being used in production projects, even though I have only done general testing. That is why the risk of using the code lies entirely with you.
|
688
|
+
Your wishes, objections, comments are welcome.
|
579
689
|
|
580
|
-
**Warning**: don't access the tree node fields directly! Most of them have been removed as unnecessary. In the future, only `tn_parent` and `tn_priority` will be kept. Use the functions described in the documentation above or the documentation for the [original application](https://github.com/fabiocaccamo/django-treenode).
|
581
690
|
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
* [Select2-to-Tree](https://github.com/clivezhg/select2-to-tree) Select2 extension by [clivezhg](https://github.com/clivezhg)
|
691
|
+
# Django-fast-treenode
|
692
|
+
## License
|
693
|
+
Released under [MIT License](https://github.com/TimurKady/django-fast-treenode/blob/main/LICENSE).
|
586
694
|
|
587
|
-
|
695
|
+
## Cautions
|
696
|
+
**Warning**: Do not access the tree node fields directly! Most of *django-treenode* model fields have been removed as unnecessary. Now only `tn_parent` and `tn_priority` are supported and will be kept in the future.
|
588
697
|
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
* to be happy, to don't worry, until die.
|
698
|
+
**Risks of Direct Field Access:**
|
699
|
+
- **Database Integrity Issues**: Directly modifying fields may break tree integrity, causing inconsistent parent-child relationships.
|
700
|
+
- **Loss of Cached Data**: The caching system relies on controlled updates. Bypassing methods like `set_parent()` or `update_tree()` may lead to outdated or incorrect data.
|
701
|
+
- **Unsupported Behavior**: Future versions may change field structures or remove unnecessary fields. Relying on them directly risks breaking compatibility.
|
594
702
|
|
703
|
+
Instead, always use the **documented methods** described above or refer to the [original application documentation](https://github.com/fabiocaccamo/django-treenode).
|
595
704
|
|
596
|
-
|
705
|
+
## Credits
|
706
|
+
This software contains, uses, and includes, in a modified form, [django-treenode](https://github.com/fabiocaccamo/django-treenode) by [Fabio Caccamo](https://github.com/fabiocaccamo). Special thanks to [Mathieu Leplatre](https://blog.mathieu-leplatre.info/pages/about.html) for the advice used in writing this application.
|
@@ -0,0 +1,41 @@
|
|
1
|
+
treenode/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
|
+
treenode/admin.py,sha256=x5vJDiZjqcsUAVlK1qkZPK66lQeJq8zYgWwwejentYM,14077
|
3
|
+
treenode/apps.py,sha256=M0O9IKEnJZFfhfz12v4wksYJ-0ECyj1Cy3qXrfywos8,472
|
4
|
+
treenode/cache.py,sha256=Z_FpaS0vTKXqAI4n1QkZ7A_ILsLU3Q8rLgerA6pYyAA,7210
|
5
|
+
treenode/forms.py,sha256=imoLzr7qFlOBdeMQK12rAFp6hINpe0PS_U4-V8RRcDU,2802
|
6
|
+
treenode/managers.py,sha256=7z8GU64A2_jEonJyQDTyIpdOocaBbM352DkwZTHjdQk,10828
|
7
|
+
treenode/urls.py,sha256=7N0d4XiI6880sc8P89eWGr-ZjmOqPorA-fWfcnviqAM,876
|
8
|
+
treenode/version.py,sha256=-zaHoXRvTvJ0QzwA9ocYp7O38iBtIarACZbCNzwyc4s,222
|
9
|
+
treenode/views.py,sha256=vBDIxmYXBwmJxRnInvUVGy75FQmt-XN_HnEaKIu-fVs,3365
|
10
|
+
treenode/widgets.py,sha256=4Q6WlPPT5fggEuTXiZ_Z40pjb46CylSp28pa0xBT_Ps,2079
|
11
|
+
treenode/docs/Documentation,sha256=6USAESU8MuY1vlj95yY8S6T0o_0RsktGv6S_0SdSkwk,21030
|
12
|
+
treenode/models/__init__.py,sha256=gjDwVai0jf-l0hMaeeEBTYLR-DXkxUZMLUMGGs_tnuo,83
|
13
|
+
treenode/models/classproperty.py,sha256=IrwBWpmyjsAXpkpfDSOIMsnX6EMcbXql3mZjurHgRcw,556
|
14
|
+
treenode/models/closure.py,sha256=chTa9T9yC3H_2LaZXR7KLdNh1pc50iUolut5GB4Bm-Q,5297
|
15
|
+
treenode/models/factory.py,sha256=Wt1szWhbeICPwm0-RUy9p4VovcxltHECVxTSRyCQHc8,2100
|
16
|
+
treenode/models/proxy.py,sha256=6BFElk_NL1ARTEAikOOfMneUK5wEjofNnfXQWFSZUsA,21766
|
17
|
+
treenode/static/.gitkeep,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
18
|
+
treenode/static/treenode/.gitkeep,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
|
19
|
+
treenode/static/treenode/css/.gitkeep,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
|
20
|
+
treenode/static/treenode/css/tree_widget.css,sha256=Qsnr9cExetL7BFKErRSns4APzM8-9DM4g6nqMelPzUI,1972
|
21
|
+
treenode/static/treenode/css/treenode_admin.css,sha256=GiCJ_zNZs7JmJgjCHsn1tJinNEU_lTOYYPZ7S0fnvis,2195
|
22
|
+
treenode/static/treenode/js/.gitkeep,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
|
23
|
+
treenode/static/treenode/js/tree_widget.js,sha256=Du3a76tojdIqWndji88Omt5MvajXK7GpypC9DYIFBMk,6571
|
24
|
+
treenode/static/treenode/js/treenode_admin.js,sha256=3fdvy1VoHb3rmzI19YXw4JPt6ZGKn_AhTEky8YQEilU,6821
|
25
|
+
treenode/templates/.gitkeep,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
|
26
|
+
treenode/templates/admin/.gitkeep,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
|
27
|
+
treenode/templates/admin/export_success.html,sha256=xN2D-BCH249CJB10fo_vHYUyFenQ9mFKqq7UTWcrXS4,747
|
28
|
+
treenode/templates/admin/tree_node_changelist.html,sha256=ykksipIBMy2LvH6UqPuM-y00UlXAjsypMHqiMm_KlTg,261
|
29
|
+
treenode/templates/admin/tree_node_export.html,sha256=vJxEoGI-US6VdFddxAFgL5r3MgGt6mgA43vltCsbA2k,1043
|
30
|
+
treenode/templates/admin/tree_node_import.html,sha256=ZFoveJ08X99EGiwFCfQowXI9oS9VgcFtRLYVDIWq-Fg,969
|
31
|
+
treenode/templates/widgets/tree_widget.css,sha256=2bEaxu1x7QJZ7erbs2SLMaxeaiMkjQXadfcDEW8wfok,551
|
32
|
+
treenode/templates/widgets/tree_widget.html,sha256=GKcCU-B2FkkJ2BSOuXOw9e_PdYTtADcvyITEXqOlZ9Y,723
|
33
|
+
treenode/utils/__init__.py,sha256=jAVT-uNGQDKPVq5ET4JE2GhRpzbxFdHU25w9sLC3_To,134
|
34
|
+
treenode/utils/base36.py,sha256=ydgu9hqDaK-WyS8zG-mtSWo7hJqbB4iHqkGz4-IVrb4,834
|
35
|
+
treenode/utils/exporter.py,sha256=l-IEsk2fK8xe-E-Hi7SMOV7ZIwxM6mZih5-0rhvsx9E,5396
|
36
|
+
treenode/utils/importer.py,sha256=n23PBFPXN-6S_Dl8Qmx56sp0eLy_lWfpxrzJqwygQf0,14190
|
37
|
+
django_fast_treenode-2.0.0.dist-info/LICENSE,sha256=GiiEe4Y9oOCbn9eGuNew1mMYHU_bJWaCK9zOusnKvvU,1091
|
38
|
+
django_fast_treenode-2.0.0.dist-info/METADATA,sha256=4KtUbAU7CMjjTFPk_5cv5jfkPZTID5Onf-U8p-gycr8,23215
|
39
|
+
django_fast_treenode-2.0.0.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
40
|
+
django_fast_treenode-2.0.0.dist-info/top_level.txt,sha256=fmgxHbXyx1O2MPi_9kjx8aL9L-8TmV0gre4Go8XgqFk,9
|
41
|
+
django_fast_treenode-2.0.0.dist-info/RECORD,,
|