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.
Files changed (50) hide show
  1. {django_fast_treenode-1.1.3.dist-info → django_fast_treenode-2.0.0.dist-info}/METADATA +156 -46
  2. django_fast_treenode-2.0.0.dist-info/RECORD +41 -0
  3. {django_fast_treenode-1.1.3.dist-info → django_fast_treenode-2.0.0.dist-info}/WHEEL +1 -1
  4. treenode/__init__.py +0 -7
  5. treenode/admin.py +327 -82
  6. treenode/apps.py +20 -3
  7. treenode/cache.py +231 -0
  8. treenode/docs/Documentation +130 -54
  9. treenode/forms.py +75 -19
  10. treenode/managers.py +260 -48
  11. treenode/models/__init__.py +7 -0
  12. treenode/models/classproperty.py +24 -0
  13. treenode/models/closure.py +168 -0
  14. treenode/models/factory.py +71 -0
  15. treenode/models/proxy.py +650 -0
  16. treenode/static/treenode/css/tree_widget.css +62 -0
  17. treenode/static/treenode/css/treenode_admin.css +106 -0
  18. treenode/static/treenode/js/tree_widget.js +161 -0
  19. treenode/static/treenode/js/treenode_admin.js +171 -0
  20. treenode/templates/admin/export_success.html +26 -0
  21. treenode/templates/admin/tree_node_changelist.html +11 -0
  22. treenode/templates/admin/tree_node_export.html +27 -0
  23. treenode/templates/admin/tree_node_import.html +27 -0
  24. treenode/templates/widgets/tree_widget.css +23 -0
  25. treenode/templates/widgets/tree_widget.html +21 -0
  26. treenode/urls.py +34 -0
  27. treenode/utils/__init__.py +4 -0
  28. treenode/utils/base36.py +35 -0
  29. treenode/utils/exporter.py +141 -0
  30. treenode/utils/importer.py +296 -0
  31. treenode/version.py +11 -1
  32. treenode/views.py +102 -2
  33. treenode/widgets.py +49 -27
  34. django_fast_treenode-1.1.3.dist-info/RECORD +0 -33
  35. treenode/compat.py +0 -8
  36. treenode/factory.py +0 -68
  37. treenode/models.py +0 -668
  38. treenode/static/select2tree/.gitkeep +0 -1
  39. treenode/static/select2tree/select2tree.css +0 -176
  40. treenode/static/select2tree/select2tree.js +0 -181
  41. treenode/static/treenode/css/treenode.css +0 -85
  42. treenode/static/treenode/js/treenode.js +0 -201
  43. treenode/templates/widgets/.gitkeep +0 -1
  44. treenode/templates/widgets/attrs.html +0 -7
  45. treenode/templates/widgets/options.html +0 -1
  46. treenode/templates/widgets/select2tree.html +0 -22
  47. treenode/tests.py +0 -3
  48. {django_fast_treenode-1.1.3.dist-info → django_fast_treenode-2.0.0.dist-info}/LICENSE +0 -0
  49. {django_fast_treenode-1.1.3.dist-info → django_fast_treenode-2.0.0.dist-info}/top_level.txt +0 -0
  50. /treenode/{docs → templates/admin}/.gitkeep +0 -0
@@ -1,28 +1,44 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: django-fast-treenode
3
- Version: 1.1.3
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: timurkady@yandex.com
8
- License: MIT
9
- Classifier: Environment :: Web Environment
10
- Classifier: Framework :: Django
11
- Classifier: Framework :: Django :: 3.0
12
- Classifier: Intended Audience :: Developers
13
- Classifier: License :: OSI Approved :: MIT License
14
- Classifier: Operating System :: OS Independent
15
- Classifier: Programming Language :: Python :: 3
16
- Classifier: Programming Language :: Python :: 3.9
17
- Classifier: Programming Language :: Python :: 3.10
18
- Classifier: Programming Language :: Python :: 3.11
19
- Classifier: Framework :: Django
20
- Classifier: Framework :: Django :: 3.0
21
- Classifier: Framework :: Django :: 4.0
22
- Requires-Python: >=3.8
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 >=3.0
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
- When updating an existing project, simply call ```cls.update_tree()``` function once.
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
- ## Usage
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** if `cascade=True` (default behaviour), children and descendants will be deleted too,
217
- otherwise children's parent will be set to `None` (then children become roots):
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
- obj.delete(cascade=True)
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
- ## License
575
- Released under [MIT License](https://github.com/TimurKady/django-fast-treenode/blob/main/LICENSE).
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
- ## Cautions
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
- ## Credits
583
- This software contains, uses, including in a modified form:
584
- * [django-treenode](https://github.com/fabiocaccamo/django-treenode) by [Fabio Caccamo](https://github.com/fabiocaccamo);
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
- Special thanks to [Mathieu Leplatre](https://blog.mathieu-leplatre.info/pages/about.html) for the advice used in writing this application
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
- ## To do
590
- Future plans:
591
- * may be will add the ability to determine the priority of the parent by any field, for example, by creation date or alphabetical order;
592
- * drug-and-drop support;
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
- Your wishes, objections, comments are welcome.
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,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.43.0)
2
+ Generator: setuptools (75.8.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
treenode/__init__.py CHANGED
@@ -1,7 +0,0 @@
1
- class classproperty(object):
2
-
3
- def __init__(self, getter):
4
- self.getter = getter
5
-
6
- def __get__(self, instance, owner):
7
- return self.getter(owner)