django-fast-treenode 3.0.6__tar.gz → 3.0.8__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.
Files changed (126) hide show
  1. {django_fast_treenode-3.0.6/django_fast_treenode.egg-info → django_fast_treenode-3.0.8}/PKG-INFO +1 -1
  2. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8/django_fast_treenode.egg-info}/PKG-INFO +1 -1
  3. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/docs/admin.md +0 -3
  4. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/pyproject.toml +1 -1
  5. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/setup.py +1 -1
  6. django_fast_treenode-3.0.8/treenode/__init__.py +1 -0
  7. django_fast_treenode-3.0.8/treenode/admin/admin.py +222 -0
  8. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/admin/mixin.py +1 -1
  9. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/managers/queries.py +18 -6
  10. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/managers/tasks.py +1 -1
  11. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/models/models.py +2 -2
  12. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/static/css/treenode_admin.css +21 -0
  13. django_fast_treenode-3.0.8/treenode/static/js/treenode_admin.js +322 -0
  14. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/static/vendors/jquery-ui/AUTHORS.txt +384 -384
  15. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/static/vendors/jquery-ui/LICENSE.txt +43 -43
  16. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/static/vendors/jquery-ui/external/jquery/jquery.js +10716 -10716
  17. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/static/vendors/jquery-ui/index.html +297 -297
  18. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/static/vendors/jquery-ui/jquery-ui.css +438 -438
  19. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/static/vendors/jquery-ui/jquery-ui.js +5222 -5222
  20. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/static/vendors/jquery-ui/jquery-ui.min.css +6 -6
  21. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/static/vendors/jquery-ui/jquery-ui.min.js +5 -5
  22. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/static/vendors/jquery-ui/jquery-ui.structure.css +16 -16
  23. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/static/vendors/jquery-ui/jquery-ui.structure.min.css +4 -4
  24. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/static/vendors/jquery-ui/jquery-ui.theme.css +439 -439
  25. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/static/vendors/jquery-ui/jquery-ui.theme.min.css +4 -4
  26. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/static/vendors/jquery-ui/package.json +82 -82
  27. django_fast_treenode-3.0.8/treenode/templates/treenode/admin/treenode_changelist.html +71 -0
  28. django_fast_treenode-3.0.8/treenode/templates/treenode/admin/treenode_rows.html +54 -0
  29. django_fast_treenode-3.0.8/treenode/templatetags/treenode_admin.py +89 -0
  30. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/utils/db/sqlcompat.py +1 -33
  31. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/utils/db/sqlquery.py +0 -24
  32. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/version.py +2 -2
  33. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/views/autoapi.py +91 -91
  34. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/views/autocomplete.py +52 -52
  35. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/views/children.py +41 -41
  36. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/views/common.py +23 -23
  37. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/widgets.py +0 -2
  38. django_fast_treenode-3.0.6/treenode/admin/admin.py +0 -226
  39. django_fast_treenode-3.0.6/treenode/static/js/treenode_admin.js +0 -531
  40. django_fast_treenode-3.0.6/treenode/templates/treenode/admin/treenode_changelist.html +0 -25
  41. django_fast_treenode-3.0.6/treenode/templates/treenode/admin/treenode_rows.html +0 -57
  42. django_fast_treenode-3.0.6/treenode/templatetags/treenode_admin.py +0 -46
  43. django_fast_treenode-3.0.6/treenode/utils/__init__.py +0 -0
  44. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/LICENSE +0 -0
  45. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/MANIFEST.in +0 -0
  46. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/README.md +0 -0
  47. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/django_fast_treenode.egg-info/SOURCES.txt +0 -0
  48. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/django_fast_treenode.egg-info/dependency_links.txt +0 -0
  49. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/django_fast_treenode.egg-info/requires.txt +0 -0
  50. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/django_fast_treenode.egg-info/top_level.txt +0 -0
  51. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/docs/.gitignore +0 -0
  52. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/docs/.nojekyll +0 -0
  53. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/docs/about.md +0 -0
  54. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/docs/api.md +0 -0
  55. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/docs/apifirst.md +0 -0
  56. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/docs/cache.md +0 -0
  57. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/docs/customization.md +0 -0
  58. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/docs/dnd.md +0 -0
  59. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/docs/import_export.md +0 -0
  60. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/docs/index.md +0 -0
  61. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/docs/insert-after.jpg +0 -0
  62. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/docs/insert-as-child.jpg +0 -0
  63. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/docs/installation.md +0 -0
  64. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/docs/migration.md +0 -0
  65. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/docs/models.md +0 -0
  66. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/docs/requirements.txt +0 -0
  67. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/docs/roadmap.md +0 -0
  68. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/docs/using.md +0 -0
  69. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/setup.cfg +0 -0
  70. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/tests/test_suite.py +0 -0
  71. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/admin/__init__.py +0 -0
  72. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/admin/changelist.py +0 -0
  73. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/admin/exporter.py +0 -0
  74. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/admin/importer.py +0 -0
  75. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/apps.py +0 -0
  76. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/cache.py +0 -0
  77. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/forms.py +0 -0
  78. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/managers/__init__.py +0 -0
  79. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/managers/managers.py +0 -0
  80. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/models/__init__.py +0 -0
  81. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/models/decorators.py +0 -0
  82. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/models/factory.py +0 -0
  83. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/models/mixins/__init__.py +0 -0
  84. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/models/mixins/ancestors.py +0 -0
  85. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/models/mixins/children.py +0 -0
  86. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/models/mixins/descendants.py +0 -0
  87. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/models/mixins/family.py +0 -0
  88. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/models/mixins/logical.py +0 -0
  89. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/models/mixins/node.py +0 -0
  90. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/models/mixins/properties.py +0 -0
  91. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/models/mixins/roots.py +0 -0
  92. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/models/mixins/siblings.py +0 -0
  93. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/models/mixins/tree.py +0 -0
  94. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/models/mixins/update.py +0 -0
  95. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/settings.py +0 -0
  96. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/signals.py +0 -0
  97. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/static/.gitkeep +0 -0
  98. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/static/css/.gitkeep +0 -0
  99. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/static/css/tree_widget.css +0 -0
  100. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/static/css/treenode_tabs.css +0 -0
  101. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/static/js/.gitkeep +0 -0
  102. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/static/js/lz-string.min.js +0 -0
  103. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/static/js/tree_widget.js +0 -0
  104. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/static/vendors/jquery-ui/images/ui-icons_444444_256x240.png +0 -0
  105. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/static/vendors/jquery-ui/images/ui-icons_555555_256x240.png +0 -0
  106. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/static/vendors/jquery-ui/images/ui-icons_777620_256x240.png +0 -0
  107. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/static/vendors/jquery-ui/images/ui-icons_777777_256x240.png +0 -0
  108. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/static/vendors/jquery-ui/images/ui-icons_cc0000_256x240.png +0 -0
  109. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/static/vendors/jquery-ui/images/ui-icons_ffffff_256x240.png +0 -0
  110. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/templates/.gitkeep +0 -0
  111. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/templates/treenode/.gitkeep +0 -0
  112. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/templates/treenode/admin/.gitkeep +0 -0
  113. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/templates/treenode/admin/treenode_ajax_rows.html +0 -0
  114. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/templates/treenode/admin/treenode_import_export.html +0 -0
  115. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/templates/treenode/widgets/tree_widget.html +0 -0
  116. {django_fast_treenode-3.0.6/treenode → django_fast_treenode-3.0.8/treenode/templatetags}/__init__.py +0 -0
  117. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/tests.py +0 -0
  118. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/urls.py +0 -0
  119. {django_fast_treenode-3.0.6/treenode/templatetags → django_fast_treenode-3.0.8/treenode/utils}/__init__.py +0 -0
  120. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/utils/db/__init__.py +0 -0
  121. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/utils/db/compiler.py +0 -0
  122. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/utils/db/db_vendor.py +0 -0
  123. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/utils/db/service.py +0 -0
  124. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/views/__init__.py +0 -0
  125. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/views/crud.py +0 -0
  126. {django_fast_treenode-3.0.6 → django_fast_treenode-3.0.8}/treenode/views/search.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: django-fast-treenode
3
- Version: 3.0.6
3
+ Version: 3.0.8
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
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: django-fast-treenode
3
- Version: 3.0.6
3
+ Version: 3.0.8
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
@@ -16,7 +16,6 @@ class CategoryAdmin(TreeNodeModelAdmin):
16
16
  # Set the display mode: 'accordion', 'breadcrumbs', or 'indentation'
17
17
  treenode_display_mode = TreeNodeModelAdmin.TREENODE_DISPLAY_MODE_ACCORDION
18
18
  # treenode_display_mode = TreeNodeModelAdmin.TREENODE_DISPLAY_MODE_BREADCRUMBS
19
- # treenode_display_mode = TreeNodeModelAdmin.TREENODE_DISPLAY_MODE_INDENTATION
20
19
 
21
20
  list_display = ("name",)
22
21
  search_fields = ("name",)
@@ -30,8 +29,6 @@ You can choose from three display modes:
30
29
  Expands/collapses nodes dynamically.
31
30
  - **`TREENODE_DISPLAY_MODE_BREADCRUMBS`**
32
31
  Displays the tree as a sequence of **breadcrumbs**, making it easy to navigate.
33
- - **`TREENODE_DISPLAY_MODE_INDENTATION`**
34
- Uses a **long dash** (`———`) to indicate nesting levels, providing a simple visual structure.
35
32
 
36
33
  The accordion mode is **always active**, and the setting only affects how nodes are displayed.
37
34
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "django-fast-treenode"
7
- version = "3.0.6"
7
+ version = "3.0.8"
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" }]
@@ -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.6',
5
+ version='3.0.8',
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',
@@ -0,0 +1 @@
1
+ default_app_config = 'treenode.apps.TreeNodeConfig'
@@ -0,0 +1,222 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ TreeNode Admin Model Class
4
+
5
+ Modified admin panel for django-fast-treenode. Solves the following problems:
6
+ - Set list_per_page = 10000 to display all elements at once.
7
+ - Hidden standard pagination via CSS
8
+ - Disabled counting the total number of elements to speed up loading
9
+ - Accordion works regardless of the display mode
10
+ Two modes are supported:
11
+ - Indented - with indents and icons
12
+ - Breadcrumbs - with breadcrumbs
13
+ All modes have links to editing objects.
14
+
15
+ - Expand buttons for nodes with children
16
+
17
+ Additional features:
18
+ - Control panel with "Expand All" / "Collapse All" buttons
19
+ - Saving the state of the tree between page transitions
20
+ - Smooth animations when expanding/collapsing
21
+ - Counting the total number of nodes in the tree
22
+ - Recursive hiding of grandchildren when collapsing the parent
23
+
24
+ Version: 3.1.0
25
+ Author: Timur Kady
26
+ Email: timurkady@yandex.com
27
+ """
28
+
29
+
30
+ from django.contrib import admin
31
+ from django.db import models
32
+ from django.urls import reverse
33
+ from django.utils.html import escape
34
+ from django.utils.safestring import mark_safe
35
+ from django.utils.translation import gettext_lazy as _
36
+
37
+ from .mixin import AdminMixin
38
+ from ..forms import TreeNodeForm
39
+ from ..widgets import TreeWidget
40
+ from .importer import TreeNodeImporter
41
+ from .exporter import TreeNodeExporter
42
+
43
+ import logging
44
+
45
+ logger = logging.getLogger(__name__)
46
+
47
+
48
+ class TreeNodeModelAdmin(AdminMixin, admin.ModelAdmin):
49
+ """Admin for TreeNodeModel."""
50
+
51
+ # Режимы отображения
52
+ TREENODE_DISPLAY_MODE_ACCORDION = 'accordion'
53
+ TREENODE_DISPLAY_MODE_BREADCRUMBS = 'breadcrumbs'
54
+ treenode_display_mode = TREENODE_DISPLAY_MODE_ACCORDION
55
+
56
+ form = TreeNodeForm
57
+ importer_class = None
58
+ exporter_class = None
59
+ ordering = []
60
+
61
+ formfield_overrides = {
62
+ models.ForeignKey: {'widget': TreeWidget()},
63
+ }
64
+
65
+ change_list_template = "treenode/admin/treenode_changelist.html"
66
+ import_export = True
67
+
68
+ class Media:
69
+ """Meta Class."""
70
+
71
+ css = {"all": (
72
+ "css/treenode_admin.css",
73
+ "vendors/jquery-ui/jquery-ui.css",
74
+ )}
75
+ js = (
76
+ "vendors/jquery-ui/jquery-ui.js",
77
+ # "js/lz-string.min.js",
78
+ "js/treenode_admin.js",
79
+ )
80
+
81
+ def __init__(self, model, admin_site):
82
+ """Init method."""
83
+ super().__init__(model, admin_site)
84
+
85
+ if not self.list_display:
86
+ self.list_display = [field.name for field in model._meta.fields]
87
+
88
+ self.TreeNodeImporter = self.importer_class or TreeNodeImporter
89
+ self.TreeNodeExporter = self.exporter_class or TreeNodeExporter
90
+
91
+ def drag(self, obj):
92
+ """Drag and drop сolumn."""
93
+ return mark_safe('<span class="treenode-drag-handle">&#9776;</span>')
94
+
95
+ drag.short_description = _("Move")
96
+
97
+ def toggle(self, obj):
98
+ """Toggle column."""
99
+ if obj.get_children_count() > 0:
100
+ return mark_safe(
101
+ f'<button class="treenode-toggle" data-node-id="{obj.pk}">►</button>' # noqa
102
+ )
103
+ return mark_safe('<div class="treenode-space">&nbsp;</div>')
104
+
105
+ toggle.short_description = _("Expand")
106
+
107
+ def get_changelist(self, request, **kwargs):
108
+ """Get changelist."""
109
+ ChangeList = super().get_changelist(request, **kwargs)
110
+
111
+ class NoPaginationChangeList(ChangeList):
112
+ """Suppress pagination."""
113
+
114
+ def get_results(self, request):
115
+ """Get result."""
116
+ super().get_results(request)
117
+ self.paginator.show_all = True
118
+ self.result_count = len(self.result_list)
119
+ self.full_result_count = len(self.result_list)
120
+ self.can_show_all = False
121
+ self.multi_page = False
122
+ self.actions = self.model_admin.get_actions(request)
123
+
124
+ return NoPaginationChangeList
125
+
126
+ def get_changelist_instance(self, request):
127
+ """
128
+ Get changelist instance.
129
+
130
+ Make sure our custom ChangeList is used without pagination.
131
+ """
132
+ ChangeList = self.get_changelist(request)
133
+
134
+ return ChangeList(
135
+ request,
136
+ self.model,
137
+ self.get_list_display(request),
138
+ self.get_list_display_links(
139
+ request,
140
+ self.get_list_display(request)
141
+ ),
142
+ self.get_list_filter(request),
143
+ self.date_hierarchy,
144
+ self.search_fields,
145
+ self.list_select_related,
146
+ self.list_per_page,
147
+ self.list_max_show_all,
148
+ self.list_editable,
149
+ self,
150
+ sortable_by=self.get_sortable_by(request),
151
+ search_help_text=self.get_search_help_text(request),
152
+ )
153
+
154
+ def get_queryset(self, request):
155
+ """Get queryset."""
156
+ qs = super().get_queryset(request)
157
+ return qs.select_related('parent')\
158
+ .prefetch_related('children')\
159
+ .order_by('_path')
160
+
161
+ def get_list_display(self, request):
162
+ """Get list_display."""
163
+ def treenode_field(obj):
164
+ return self._get_treenode_field_display(request, obj)
165
+
166
+ description = str(self.model._meta.verbose_name)
167
+ treenode_field.short_description = description
168
+
169
+ return (self.drag, self.toggle, treenode_field)
170
+
171
+ def get_form(self, request, obj=None, **kwargs):
172
+ """Get Form method."""
173
+ form = super().get_form(request, obj, **kwargs)
174
+ if "parent" in form.base_fields:
175
+ form.base_fields["parent"].widget = TreeWidget()
176
+ return form
177
+
178
+ def get_search_fields(self, request):
179
+ """Get search fields."""
180
+ return [getattr(self.model, 'display_field', 'id') or 'id']
181
+
182
+ def _get_treenode_field_display(self, request, obj):
183
+ """
184
+ Generate HTML to display tree nodes.
185
+
186
+ Depending on the selected display mode (accordion or breadcrumbs),
187
+ do the following:
188
+ - For accordion mode: add indents and icons.
189
+ - For breadcrumbs mode: display breadcrumb path.
190
+ """
191
+ level = obj.get_depth()
192
+ display_field = getattr(obj, "display_field", None)
193
+ edit_url = reverse(
194
+ f"admin:{obj._meta.app_label}_{obj._meta.model_name}_change",
195
+ args=[obj.pk]
196
+ )
197
+ icon = ""
198
+ text = ""
199
+ padding = ""
200
+ closing = ""
201
+
202
+ if self.treenode_display_mode == self.TREENODE_DISPLAY_MODE_ACCORDION:
203
+ icon = "📄 " if obj.is_leaf() else "📁 "
204
+ text = getattr(obj, display_field, str(obj))
205
+ padding = f'<span style="padding-left: {level * 1.5}em;">'
206
+ closing = "</span>"
207
+ elif self.treenode_display_mode == self.TREENODE_DISPLAY_MODE_BREADCRUMBS: # noqa
208
+ if display_field:
209
+ breadcrumbs = obj.get_breadcrumbs(attr=display_field)
210
+ else:
211
+ breadcrumbs = [str(item) for item in obj.get_ancestors()]
212
+
213
+ text = "/" + "/".join([escape(label) for label in breadcrumbs])
214
+
215
+ content = f'{padding}{icon}<a href="{edit_url}">{escape(text)}</a>{closing}' # noqa
216
+ return mark_safe(content)
217
+
218
+ def get_list_per_page(self, request):
219
+ """Get list per page."""
220
+ return 999999
221
+
222
+ # The End
@@ -4,7 +4,7 @@ TreeNode Admin Model Class Mixin
4
4
 
5
5
  Views for AdminModel
6
6
 
7
- Version: 3.0.0
7
+ Version: 3.0.7
8
8
  Author: Timur Kady
9
9
  Email: timurkady@yandex.com
10
10
  """
@@ -5,14 +5,13 @@ Low-level SQL Query Manager.
5
5
  Encapsulates all logic to retrieve related primary keys based on relationships
6
6
  (e.g., ancestors, children, descendants, siblings, family, root) using raw SQL.
7
7
 
8
- Version: 3.0.4
8
+ Version: 3.0.0
9
9
  Author: Timur Kady
10
10
  Email: timurkady@yandex.com
11
11
  """
12
12
 
13
13
 
14
14
  from django.db import connection
15
- from ..utils.db.sqlcompat import SQLCompat
16
15
 
17
16
 
18
17
  class TreeQuery:
@@ -33,6 +32,19 @@ class TreeQuery:
33
32
  cursor.execute(sql, params)
34
33
  return cursor.fetchall()
35
34
 
35
+ def wrap_union_all(self, queries):
36
+ """
37
+ Combine multiple SQL queries using UNION ALL.
38
+
39
+ Each query is a tuple: (sql, params).
40
+ Returns a tuple: (combined_sql, combined_params).
41
+ """
42
+ union_query = " UNION ALL ".join(f"({q[0]})" for q in queries)
43
+ combined_params = []
44
+ for q in queries:
45
+ combined_params.extend(q[1])
46
+ return union_query, combined_params
47
+
36
48
  def order_by(self, sql, order_by_clause):
37
49
  """Wrap the SQL in an outer query to enforce ordering."""
38
50
  return f"SELECT * FROM ({sql}) AS combined ORDER BY {order_by_clause}"
@@ -64,7 +76,7 @@ class TreeQuery:
64
76
  if include_self:
65
77
  sql2 = f"SELECT id, priority FROM {self.db_table} WHERE id = %s"
66
78
  params2 = [self.node.pk]
67
- combined_sql, combined_params = SQLCompat.wrap_union_all(
79
+ combined_sql, combined_params = self.wrap_union_all(
68
80
  [(sql1, params1), (sql2, params2)])
69
81
  sql = self.order_by(combined_sql, "priority")
70
82
  return sql, combined_params
@@ -103,7 +115,7 @@ class TreeQuery:
103
115
  FROM {self.db_table}
104
116
  WHERE id = %s
105
117
  """
106
- union_sql, union_params = SQLCompat.wrap_union_all([
118
+ union_sql, union_params = self.wrap_union_all([
107
119
  (base_sql, params),
108
120
  (sql_self, [self.node.pk])
109
121
  ])
@@ -136,7 +148,7 @@ class TreeQuery:
136
148
 
137
149
  if include_self:
138
150
  sql_self = f"SELECT id, _depth, priority FROM {self.db_table} WHERE id = %s" # noqa: D501
139
- union_sql, union_params = SQLCompat.wrap_union_all(
151
+ union_sql, union_params = self.wrap_union_all(
140
152
  [(base_sql, params), (sql_self, [self.node.pk])])
141
153
  else:
142
154
  union_sql, union_params = base_sql, params
@@ -186,7 +198,7 @@ class TreeQuery:
186
198
  if include_self:
187
199
  sql_self = f"SELECT id, _depth, priority FROM {self.db_table} WHERE id = %s" # noqa: D501
188
200
  queries.append((sql_self, [self.node.pk]))
189
- combined_sql, combined_params = SQLCompat.wrap_union_all(queries)
201
+ combined_sql, combined_params = self.wrap_union_all(queries)
190
202
  combined_sql = self.order_by(combined_sql, "_depth, priority")
191
203
  return combined_sql, combined_params
192
204
 
@@ -2,7 +2,7 @@
2
2
  """
3
3
  TreeNode TaskQuery manager
4
4
 
5
- Version: 3.0.4
5
+ Version: 3.0.1
6
6
  Author: Timur Kady
7
7
  Email: timurkady@yandex.com
8
8
  """
@@ -14,7 +14,7 @@ Features:
14
14
  - Provides a caching mechanism to optimize performance.
15
15
  - Includes methods for tree traversal, manipulation, and serialization.
16
16
 
17
- Version: 3.0.0
17
+ Version: 3.0.7
18
18
  Author: Timur Kady
19
19
  Email: timurkady@yandex.com
20
20
 
@@ -122,7 +122,7 @@ class TreeNodeModel(
122
122
 
123
123
  def __str__(self):
124
124
  """Return a human-readable string representation of an object."""
125
- field = getattr(type(self), 'display_field', None)
125
+ field = getattr(self, 'display_field', None)
126
126
  if field and hasattr(self, field):
127
127
  return str(getattr(self, field))
128
128
  return f'Node {self.pk}'
@@ -66,6 +66,27 @@ Email: timurkady@yandex.com
66
66
  opacity: 1.0;
67
67
  }
68
68
 
69
+ .treenode-toolbar{
70
+ display: flex;
71
+ }
72
+
73
+ .treenode-toolbar {
74
+ margin: 15px 0px;
75
+ }
76
+
77
+ .treenode-button {
78
+ padding: 5px !important;
79
+ margin-left: 15px !important;
80
+ }
81
+
82
+ tr.treenode-hidden {
83
+ display: none;
84
+ }
85
+
86
+ td.action-checkbox{
87
+ text-align: center;
88
+ }
89
+
69
90
  .dark-theme .treenode-toggle {
70
91
  color: #ccc;
71
92
  background-color: #444;