django-fast-treenode 1.1.1__tar.gz → 1.1.3__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. {django-fast-treenode-1.1.1/django_fast_treenode.egg-info → django_fast_treenode-1.1.3}/PKG-INFO +9 -10
  2. {django-fast-treenode-1.1.1 → django_fast_treenode-1.1.3}/README.md +2 -3
  3. {django-fast-treenode-1.1.1 → django_fast_treenode-1.1.3/django_fast_treenode.egg-info}/PKG-INFO +9 -10
  4. {django-fast-treenode-1.1.1 → django_fast_treenode-1.1.3}/setup.cfg +6 -4
  5. django_fast_treenode-1.1.3/setup.py +3 -0
  6. {django-fast-treenode-1.1.1 → django_fast_treenode-1.1.3}/treenode/admin.py +136 -136
  7. {django-fast-treenode-1.1.1 → django_fast_treenode-1.1.3}/treenode/compat.py +8 -8
  8. {django-fast-treenode-1.1.1/treenode/static/treenode/css → django_fast_treenode-1.1.3/treenode/docs}/.gitkeep +1 -1
  9. {django-fast-treenode-1.1.1 → django_fast_treenode-1.1.3}/treenode/docs/Documentation +28 -9
  10. {django-fast-treenode-1.1.1 → django_fast_treenode-1.1.3}/treenode/forms.py +32 -32
  11. {django-fast-treenode-1.1.1 → django_fast_treenode-1.1.3}/treenode/models.py +5 -6
  12. {django-fast-treenode-1.1.1/treenode/docs → django_fast_treenode-1.1.3/treenode/static/select2tree}/.gitkeep +1 -1
  13. {django-fast-treenode-1.1.1 → django_fast_treenode-1.1.3}/treenode/static/select2tree/select2tree.js +34 -24
  14. {django-fast-treenode-1.1.1 → django_fast_treenode-1.1.3}/treenode/static/treenode/.gitkeep +1 -1
  15. {django-fast-treenode-1.1.1/treenode/static/select2tree → django_fast_treenode-1.1.3/treenode/static/treenode/css}/.gitkeep +1 -1
  16. {django-fast-treenode-1.1.1 → django_fast_treenode-1.1.3}/treenode/static/treenode/css/treenode.css +84 -84
  17. django_fast_treenode-1.1.3/treenode/static/treenode/js/.gitkeep +1 -0
  18. {django-fast-treenode-1.1.1 → django_fast_treenode-1.1.3}/treenode/static/treenode/js/treenode.js +201 -201
  19. django_fast_treenode-1.1.3/treenode/templates/.gitkeep +1 -0
  20. django_fast_treenode-1.1.3/treenode/templates/widgets/.gitkeep +1 -0
  21. {django-fast-treenode-1.1.1 → django_fast_treenode-1.1.3}/treenode/version.py +1 -1
  22. django-fast-treenode-1.1.1/setup.py +0 -6
  23. django-fast-treenode-1.1.1/treenode/static/treenode/js/.gitkeep +0 -1
  24. django-fast-treenode-1.1.1/treenode/templates/.gitkeep +0 -1
  25. django-fast-treenode-1.1.1/treenode/templates/widgets/.gitkeep +0 -1
  26. {django-fast-treenode-1.1.1 → django_fast_treenode-1.1.3}/LICENSE +0 -0
  27. {django-fast-treenode-1.1.1 → django_fast_treenode-1.1.3}/MANIFEST.in +0 -0
  28. {django-fast-treenode-1.1.1 → django_fast_treenode-1.1.3}/django_fast_treenode.egg-info/SOURCES.txt +0 -0
  29. {django-fast-treenode-1.1.1 → django_fast_treenode-1.1.3}/django_fast_treenode.egg-info/dependency_links.txt +0 -0
  30. {django-fast-treenode-1.1.1 → django_fast_treenode-1.1.3}/django_fast_treenode.egg-info/requires.txt +0 -0
  31. {django-fast-treenode-1.1.1 → django_fast_treenode-1.1.3}/django_fast_treenode.egg-info/top_level.txt +0 -0
  32. {django-fast-treenode-1.1.1 → django_fast_treenode-1.1.3}/pyproject.toml +0 -0
  33. {django-fast-treenode-1.1.1 → django_fast_treenode-1.1.3}/treenode/__init__.py +0 -0
  34. {django-fast-treenode-1.1.1 → django_fast_treenode-1.1.3}/treenode/apps.py +0 -0
  35. {django-fast-treenode-1.1.1 → django_fast_treenode-1.1.3}/treenode/factory.py +0 -0
  36. {django-fast-treenode-1.1.1 → django_fast_treenode-1.1.3}/treenode/managers.py +0 -0
  37. {django-fast-treenode-1.1.1 → django_fast_treenode-1.1.3}/treenode/static/.gitkeep +0 -0
  38. {django-fast-treenode-1.1.1 → django_fast_treenode-1.1.3}/treenode/static/select2tree/select2tree.css +0 -0
  39. {django-fast-treenode-1.1.1 → django_fast_treenode-1.1.3}/treenode/templates/widgets/attrs.html +0 -0
  40. {django-fast-treenode-1.1.1 → django_fast_treenode-1.1.3}/treenode/templates/widgets/options.html +0 -0
  41. {django-fast-treenode-1.1.1 → django_fast_treenode-1.1.3}/treenode/templates/widgets/select2tree.html +0 -0
  42. {django-fast-treenode-1.1.1 → django_fast_treenode-1.1.3}/treenode/tests.py +0 -0
  43. {django-fast-treenode-1.1.1 → django_fast_treenode-1.1.3}/treenode/views.py +0 -0
  44. {django-fast-treenode-1.1.1 → django_fast_treenode-1.1.3}/treenode/widgets.py +0 -0
@@ -1,33 +1,34 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: django-fast-treenode
3
- Version: 1.1.1
3
+ Version: 1.1.3
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
7
  Author-email: timurkady@yandex.com
8
8
  License: MIT
9
- Platform: UNKNOWN
10
9
  Classifier: Environment :: Web Environment
11
10
  Classifier: Framework :: Django
12
11
  Classifier: Framework :: Django :: 3.0
13
12
  Classifier: Intended Audience :: Developers
14
13
  Classifier: License :: OSI Approved :: MIT License
15
14
  Classifier: Operating System :: OS Independent
16
- Classifier: Programming Language :: Python
17
15
  Classifier: Programming Language :: Python :: 3
18
- Classifier: Programming Language :: Python :: 3 :: Only
19
- Classifier: Programming Language :: Python :: 3.8
20
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
21
22
  Requires-Python: >=3.8
22
23
  Description-Content-Type: text/markdown
23
24
  License-File: LICENSE
25
+ Requires-Dist: Django>=3.0
24
26
 
25
27
  # Django-fast-treenode
26
28
  __Combination of Adjacency List and Closure Table__
27
29
 
28
30
  ## Functions
29
31
  Application for supporting tree (hierarchical) data structure in Django projects
30
- Application for supporting tree (hierarchical) data structure in Django projects
31
32
  * fast: the fastest of the two methods is used to process requests, combining the advantages of an **Adjacency Table** and a **Closure Table**,
32
33
  * even faster: the main resource-intensive operations are **cached**; **bulk operations** are used for inserts and changes,
33
34
  * synchronized: model instances in memory are automatically updated,
@@ -574,9 +575,9 @@ cls.update_tree()
574
575
  Released under [MIT License](https://github.com/TimurKady/django-fast-treenode/blob/main/LICENSE).
575
576
 
576
577
  ## Cautions
577
- The code provided is intended for testing by developers and is not recommended for use in production projects. Only general tests were carried out. The risk of using the code lies entirely with you.
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.
578
579
 
579
- Don't access treenode fields directly! Most of them have been removed as unnecessary. Use functions documented in the [source application](https://github.com/fabiocaccamo/django-treenode).
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).
580
581
 
581
582
  ## Credits
582
583
  This software contains, uses, including in a modified form:
@@ -593,5 +594,3 @@ Future plans:
593
594
 
594
595
 
595
596
  Your wishes, objections, comments are welcome.
596
-
597
-
@@ -3,7 +3,6 @@ __Combination of Adjacency List and Closure Table__
3
3
 
4
4
  ## Functions
5
5
  Application for supporting tree (hierarchical) data structure in Django projects
6
- Application for supporting tree (hierarchical) data structure in Django projects
7
6
  * fast: the fastest of the two methods is used to process requests, combining the advantages of an **Adjacency Table** and a **Closure Table**,
8
7
  * even faster: the main resource-intensive operations are **cached**; **bulk operations** are used for inserts and changes,
9
8
  * synchronized: model instances in memory are automatically updated,
@@ -550,9 +549,9 @@ cls.update_tree()
550
549
  Released under [MIT License](https://github.com/TimurKady/django-fast-treenode/blob/main/LICENSE).
551
550
 
552
551
  ## Cautions
553
- The code provided is intended for testing by developers and is not recommended for use in production projects. Only general tests were carried out. The risk of using the code lies entirely with you.
552
+ 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.
554
553
 
555
- Don't access treenode fields directly! Most of them have been removed as unnecessary. Use functions documented in the [source application](https://github.com/fabiocaccamo/django-treenode).
554
+ **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).
556
555
 
557
556
  ## Credits
558
557
  This software contains, uses, including in a modified form:
@@ -1,33 +1,34 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: django-fast-treenode
3
- Version: 1.1.1
3
+ Version: 1.1.3
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
7
  Author-email: timurkady@yandex.com
8
8
  License: MIT
9
- Platform: UNKNOWN
10
9
  Classifier: Environment :: Web Environment
11
10
  Classifier: Framework :: Django
12
11
  Classifier: Framework :: Django :: 3.0
13
12
  Classifier: Intended Audience :: Developers
14
13
  Classifier: License :: OSI Approved :: MIT License
15
14
  Classifier: Operating System :: OS Independent
16
- Classifier: Programming Language :: Python
17
15
  Classifier: Programming Language :: Python :: 3
18
- Classifier: Programming Language :: Python :: 3 :: Only
19
- Classifier: Programming Language :: Python :: 3.8
20
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
21
22
  Requires-Python: >=3.8
22
23
  Description-Content-Type: text/markdown
23
24
  License-File: LICENSE
25
+ Requires-Dist: Django>=3.0
24
26
 
25
27
  # Django-fast-treenode
26
28
  __Combination of Adjacency List and Closure Table__
27
29
 
28
30
  ## Functions
29
31
  Application for supporting tree (hierarchical) data structure in Django projects
30
- Application for supporting tree (hierarchical) data structure in Django projects
31
32
  * fast: the fastest of the two methods is used to process requests, combining the advantages of an **Adjacency Table** and a **Closure Table**,
32
33
  * even faster: the main resource-intensive operations are **cached**; **bulk operations** are used for inserts and changes,
33
34
  * synchronized: model instances in memory are automatically updated,
@@ -574,9 +575,9 @@ cls.update_tree()
574
575
  Released under [MIT License](https://github.com/TimurKady/django-fast-treenode/blob/main/LICENSE).
575
576
 
576
577
  ## Cautions
577
- The code provided is intended for testing by developers and is not recommended for use in production projects. Only general tests were carried out. The risk of using the code lies entirely with you.
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.
578
579
 
579
- Don't access treenode fields directly! Most of them have been removed as unnecessary. Use functions documented in the [source application](https://github.com/fabiocaccamo/django-treenode).
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).
580
581
 
581
582
  ## Credits
582
583
  This software contains, uses, including in a modified form:
@@ -593,5 +594,3 @@ Future plans:
593
594
 
594
595
 
595
596
  Your wishes, objections, comments are welcome.
596
-
597
-
@@ -4,7 +4,7 @@ tag_date = 0
4
4
 
5
5
  [metadata]
6
6
  name = django-fast-treenode
7
- version = 1.1.1
7
+ version = 1.1.3
8
8
  description = Application for supporting tree (hierarchical) data structure in Django projects
9
9
  long_description_content_type = text/markdown
10
10
  long_description = file: README.md
@@ -19,11 +19,13 @@ classifiers =
19
19
  Intended Audience :: Developers
20
20
  License :: OSI Approved :: MIT License
21
21
  Operating System :: OS Independent
22
- Programming Language :: Python
23
22
  Programming Language :: Python :: 3
24
- Programming Language :: Python :: 3 :: Only
25
- Programming Language :: Python :: 3.8
26
23
  Programming Language :: Python :: 3.9
24
+ Programming Language :: Python :: 3.10
25
+ Programming Language :: Python :: 3.11
26
+ Framework :: Django
27
+ Framework :: Django :: 3.0
28
+ Framework :: Django :: 4.0
27
29
 
28
30
  [options]
29
31
  include_package_data = true
@@ -0,0 +1,3 @@
1
+ from setuptools import setup
2
+
3
+ setup()
@@ -1,136 +1,136 @@
1
- # -*- coding: utf-8 -*-
2
- """
3
- TreeNode Admin Module
4
-
5
- """
6
-
7
- from django.contrib import admin
8
- from django.utils.safestring import mark_safe
9
- from django.contrib.admin.views.main import ChangeList
10
- from .forms import TreeNodeForm
11
-
12
-
13
- class NoPkDescOrderedChangeList(ChangeList):
14
- def get_ordering(self, request, queryset):
15
- rv = super().get_ordering(request, queryset)
16
- rv = list(rv)
17
- rv.remove('-pk') if '-pk' in rv else None
18
- return tuple()
19
-
20
- def get_queryset(self, request):
21
- qs = self.model.objects.all()
22
- return qs.select_related('tn_parent')
23
-
24
-
25
- class TreeNodeModelAdmin(admin.ModelAdmin):
26
-
27
- TREENODE_DISPLAY_MODE_ACCORDION = 'accordion'
28
- TREENODE_DISPLAY_MODE_BREADCRUMBS = 'breadcrumbs'
29
- TREENODE_DISPLAY_MODE_INDENTATION = 'indentation'
30
-
31
- treenode_display_mode = TREENODE_DISPLAY_MODE_INDENTATION
32
-
33
- form = TreeNodeForm
34
- list_per_page = 1000
35
-
36
- def get_list_display(self, request):
37
- base_list_display = super(
38
- TreeNodeModelAdmin, self).get_list_display(request)
39
- base_list_display = list(base_list_display)
40
-
41
- def treenode_field_display(obj):
42
- return self._get_treenode_field_display(request, obj)
43
-
44
- treenode_field_display.short_description = self.model._meta.verbose_name
45
- treenode_field_display.allow_tags = True
46
-
47
- if len(base_list_display) == 1 and base_list_display[0] == '__str__':
48
- return (treenode_field_display, )
49
- else:
50
- treenode_display_field = getattr(
51
- self.model, 'treenode_display_field')
52
- if len(base_list_display) >= 1 and base_list_display[0] == treenode_display_field:
53
- base_list_display.pop(0)
54
- return (treenode_field_display, ) + tuple(base_list_display)
55
-
56
- return base_list_display
57
-
58
- def get_changelist(self, request):
59
- return NoPkDescOrderedChangeList
60
-
61
- def get_ordering(self, request):
62
- return None
63
-
64
- def list_to_queryset(self, model, data):
65
- from django.db.models.base import ModelBase
66
-
67
- if not isinstance(model, ModelBase):
68
- raise ValueError(
69
- "%s must be Model" % model
70
- )
71
- if not isinstance(data, list):
72
- raise ValueError(
73
- "%s must be List Object" % data
74
- )
75
-
76
- pk_list = [obj.pk for obj in data]
77
- return model.objects.filter(pk__in=pk_list)
78
-
79
- def _use_treenode_display_mode(self, request, obj):
80
- querystring = (request.GET.urlencode() or '')
81
- return len(querystring) <= 2
82
-
83
- def _get_treenode_display_mode(self, request, obj):
84
- return self.treenode_display_mode
85
-
86
- def _get_treenode_field_default_display(self, obj):
87
- return self._get_treenode_field_display_with_breadcrumbs(obj)
88
-
89
- def _get_treenode_field_display(self, request, obj):
90
- if not self._use_treenode_display_mode(request, obj):
91
- return self._get_treenode_field_default_display(obj)
92
- display_mode = self._get_treenode_display_mode(request, obj)
93
- if display_mode == TreeNodeModelAdmin.TREENODE_DISPLAY_MODE_ACCORDION:
94
- return self._get_treenode_field_display_with_accordion(obj)
95
- elif display_mode == TreeNodeModelAdmin.TREENODE_DISPLAY_MODE_BREADCRUMBS:
96
- return self._get_treenode_field_display_with_breadcrumbs(obj)
97
- elif display_mode == TreeNodeModelAdmin.TREENODE_DISPLAY_MODE_INDENTATION:
98
- return self._get_treenode_field_display_with_indentation(obj)
99
- else:
100
- return self._get_treenode_field_default_display(obj)
101
-
102
- def _get_treenode_field_display_with_accordion(self, obj):
103
- tn_namespace = '%s.%s' % (obj.__module__, obj.__class__.__name__, )
104
- tn_namespace_key = tn_namespace.lower().replace('.', '_')
105
- return mark_safe(''
106
- '<span class="treenode"'
107
- ' data-treenode-type="%s"'
108
- ' data-treenode-pk="%s"'
109
- ' data-treenode-accordion="1"'
110
- ' data-treenode-depth="%s"'
111
- ' data-treenode-level="%s"'
112
- ' data-treenode-parent="%s">%s</span>' % (
113
- tn_namespace_key,
114
- str(obj.pk),
115
- str(obj.depth),
116
- str(obj.level),
117
- str(obj.tn_parent_id or ''),
118
- obj.get_display(indent=False), ))
119
-
120
- def _get_treenode_field_display_with_breadcrumbs(self, obj):
121
- obj_display = ''
122
- for obj_ancestor in obj.get_ancestors():
123
- obj_ancestor_display = obj_ancestor.get_display(indent=False)
124
- obj_display += '<span class="treenode-breadcrumbs">%s</span>' % (
125
- obj_ancestor_display, )
126
- obj_display += obj.get_display(indent=False)
127
- return mark_safe('<span class="treenode">%s</span>' % (obj_display, ))
128
-
129
- def _get_treenode_field_display_with_indentation(self, obj):
130
- obj_display = '<span class="treenode-indentation">&mdash;</span>' * obj.ancestors_count
131
- obj_display += obj.get_display(indent=False)
132
- return mark_safe('<span class="treenode">%s</span>' % (obj_display, ))
133
-
134
- class Media:
135
- css = {'all': ('treenode/css/treenode.css',)}
136
- js = ['treenode/js/treenode.js']
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ TreeNode Admin Module
4
+
5
+ """
6
+
7
+ from django.contrib import admin
8
+ from django.utils.safestring import mark_safe
9
+ from django.contrib.admin.views.main import ChangeList
10
+ from .forms import TreeNodeForm
11
+
12
+
13
+ class NoPkDescOrderedChangeList(ChangeList):
14
+ def get_ordering(self, request, queryset):
15
+ rv = super().get_ordering(request, queryset)
16
+ rv = list(rv)
17
+ rv.remove('-pk') if '-pk' in rv else None
18
+ return tuple()
19
+
20
+ def get_queryset(self, request):
21
+ qs = self.model.objects.all()
22
+ return qs.select_related('tn_parent')
23
+
24
+
25
+ class TreeNodeModelAdmin(admin.ModelAdmin):
26
+
27
+ TREENODE_DISPLAY_MODE_ACCORDION = 'accordion'
28
+ TREENODE_DISPLAY_MODE_BREADCRUMBS = 'breadcrumbs'
29
+ TREENODE_DISPLAY_MODE_INDENTATION = 'indentation'
30
+
31
+ treenode_display_mode = TREENODE_DISPLAY_MODE_INDENTATION
32
+
33
+ form = TreeNodeForm
34
+ list_per_page = 1000
35
+
36
+ def get_list_display(self, request):
37
+ base_list_display = super(
38
+ TreeNodeModelAdmin, self).get_list_display(request)
39
+ base_list_display = list(base_list_display)
40
+
41
+ def treenode_field_display(obj):
42
+ return self._get_treenode_field_display(request, obj)
43
+
44
+ treenode_field_display.short_description = self.model._meta.verbose_name
45
+ treenode_field_display.allow_tags = True
46
+
47
+ if len(base_list_display) == 1 and base_list_display[0] == '__str__':
48
+ return (treenode_field_display, )
49
+ else:
50
+ treenode_display_field = getattr(
51
+ self.model, 'treenode_display_field')
52
+ if len(base_list_display) >= 1 and base_list_display[0] == treenode_display_field:
53
+ base_list_display.pop(0)
54
+ return (treenode_field_display, ) + tuple(base_list_display)
55
+
56
+ return base_list_display
57
+
58
+ def get_changelist(self, request):
59
+ return NoPkDescOrderedChangeList
60
+
61
+ def get_ordering(self, request):
62
+ return None
63
+
64
+ def list_to_queryset(self, model, data):
65
+ from django.db.models.base import ModelBase
66
+
67
+ if not isinstance(model, ModelBase):
68
+ raise ValueError(
69
+ "%s must be Model" % model
70
+ )
71
+ if not isinstance(data, list):
72
+ raise ValueError(
73
+ "%s must be List Object" % data
74
+ )
75
+
76
+ pk_list = [obj.pk for obj in data]
77
+ return model.objects.filter(pk__in=pk_list)
78
+
79
+ def _use_treenode_display_mode(self, request, obj):
80
+ querystring = (request.GET.urlencode() or '')
81
+ return len(querystring) <= 2
82
+
83
+ def _get_treenode_display_mode(self, request, obj):
84
+ return self.treenode_display_mode
85
+
86
+ def _get_treenode_field_default_display(self, obj):
87
+ return self._get_treenode_field_display_with_breadcrumbs(obj)
88
+
89
+ def _get_treenode_field_display(self, request, obj):
90
+ if not self._use_treenode_display_mode(request, obj):
91
+ return self._get_treenode_field_default_display(obj)
92
+ display_mode = self._get_treenode_display_mode(request, obj)
93
+ if display_mode == TreeNodeModelAdmin.TREENODE_DISPLAY_MODE_ACCORDION:
94
+ return self._get_treenode_field_display_with_accordion(obj)
95
+ elif display_mode == TreeNodeModelAdmin.TREENODE_DISPLAY_MODE_BREADCRUMBS:
96
+ return self._get_treenode_field_display_with_breadcrumbs(obj)
97
+ elif display_mode == TreeNodeModelAdmin.TREENODE_DISPLAY_MODE_INDENTATION:
98
+ return self._get_treenode_field_display_with_indentation(obj)
99
+ else:
100
+ return self._get_treenode_field_default_display(obj)
101
+
102
+ def _get_treenode_field_display_with_accordion(self, obj):
103
+ tn_namespace = '%s.%s' % (obj.__module__, obj.__class__.__name__, )
104
+ tn_namespace_key = tn_namespace.lower().replace('.', '_')
105
+ return mark_safe(''
106
+ '<span class="treenode"'
107
+ ' data-treenode-type="%s"'
108
+ ' data-treenode-pk="%s"'
109
+ ' data-treenode-accordion="1"'
110
+ ' data-treenode-depth="%s"'
111
+ ' data-treenode-level="%s"'
112
+ ' data-treenode-parent="%s">%s</span>' % (
113
+ tn_namespace_key,
114
+ str(obj.pk),
115
+ str(obj.depth),
116
+ str(obj.level),
117
+ str(obj.tn_parent_id or ''),
118
+ obj.get_display(indent=False), ))
119
+
120
+ def _get_treenode_field_display_with_breadcrumbs(self, obj):
121
+ obj_display = ''
122
+ for obj_ancestor in obj.get_ancestors():
123
+ obj_ancestor_display = obj_ancestor.get_display(indent=False)
124
+ obj_display += '<span class="treenode-breadcrumbs">%s</span>' % (
125
+ obj_ancestor_display, )
126
+ obj_display += obj.get_display(indent=False)
127
+ return mark_safe('<span class="treenode">%s</span>' % (obj_display, ))
128
+
129
+ def _get_treenode_field_display_with_indentation(self, obj):
130
+ obj_display = '<span class="treenode-indentation">&mdash;</span>' * obj.ancestors_count
131
+ obj_display += obj.get_display(indent=False)
132
+ return mark_safe('<span class="treenode">%s</span>' % (obj_display, ))
133
+
134
+ class Media:
135
+ css = {'all': ('treenode/css/treenode.css',)}
136
+ js = ['treenode/js/treenode.js']
@@ -1,8 +1,8 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- import django
4
-
5
- if django.VERSION >= (3, 0):
6
- from django.utils.encoding import force_str
7
- else:
8
- from django.utils.encoding import force_text as force_str
1
+ # -*- coding: utf-8 -*-
2
+
3
+ import django
4
+
5
+ if django.VERSION >= (3, 0):
6
+ from django.utils.encoding import force_str
7
+ else:
8
+ from django.utils.encoding import force_text as force_str
@@ -1,15 +1,15 @@
1
1
  # Django-fast-treenode
2
2
  __Combination of Adjacency List and Closure Table__
3
3
 
4
- ## Functions
4
+ ## Features
5
5
  Application for supporting tree (hierarchical) data structure in Django projects
6
- * Faster: resource-intensive operations are cached; bulk operations are used for inserts and changes,
7
- * synchronized: model instances in memory are automatically updated,
8
- * compatibility: you can easily add a tree node to existing projects using TreeNode without changing the code,
6
+ * faster,
7
+ * synced: in-memory model instances are automatically updated,
8
+ * compatibility: you can easily add treenode to existing projects,
9
9
  * no dependencies,
10
- * easy setup: just extend the abstract model/model-admin,
11
- * admin integration: visualization options (accordion, breadcrumbs or padding),
12
- * widget: Built-in Select2-to-Tree extends Select2 to support arbitrary nesting levels.
10
+ * easy configuration: just extend the abstract model / model-admin,
11
+ * admin integration: visualization options (accordion, breadcrumbs or indentation),
12
+ * widget: build-in Select2-to-Tree extends Select2 to support arbitrary level of nesting.
13
13
 
14
14
  ## Debut idea
15
15
  This is a modification of the reusable [django-treenode](https://github.com/fabiocaccamo/django-treenode) application developed by [Fabio Caccamo](https://github.com/fabiocaccamo).
@@ -44,7 +44,7 @@ You can easily find additional information on your own on the Internet.
44
44
 
45
45
  ## Quick start
46
46
  1. Run ```pip install django-fast-treenode```
47
- 2. Add ```treenode``` to ```settings.INSTALLED_APPS```
47
+ 2. Add ```django-fast-treenode``` to ```settings.INSTALLED_APPS```
48
48
  3. Make your model inherit from ```treenode.models.TreeNodeModel``` (described below)
49
49
  4. Make your model-admin inherit from ```treenode.admin.TreeNodeModelAdmin``` (described below)
50
50
  5. Run python manage.py makemigrations and ```python manage.py migrate```
@@ -157,6 +157,7 @@ class YoursForm(TreeNodeForm):
157
157
  - [`get_last_child`](#get_last_child)
158
158
  - [`get_level`](#get_level)
159
159
  - [`get_order`](#get_order)
160
+ - [`get_ordered_queryset`](#get_ordered_queryset)
160
161
  - [`get_parent`](#get_parent)
161
162
  - [`get_parent_pk`](#get_parent_pk)
162
163
  - [`set_parent`](#set_parent)
@@ -360,6 +361,23 @@ obj.get_order()
360
361
  obj.order
361
362
  ```
362
363
 
364
+ #### `get_ordered_queryset`
365
+ Returns a queryset of nodes ordered by tn_priority each node.
366
+ ```python
367
+ cls.get_ordered_queryset()
368
+ ```
369
+ For example:
370
+ - A.1
371
+ - A.1.1
372
+ - A.1.1.1
373
+ - A.1.1.2
374
+ - A.2
375
+ - A.2.1
376
+ - ...
377
+
378
+ This method uses a lot of memory, ```RawSQL()``` and ```.extra()``` QuerySet method. Use of this method is deprecated due to concerns that Django's ```.extra()``` method **will be deprecated in the future**.
379
+ Use it only if you cannot otherwise assemble an ordered tree from an Adjacency Table and a Closure Table. In most cases, the data in one Adjacency Table is sufficient for such an assembly. You can easily find the corresponding algorithms (two-pass and one-pass) on the Internet.
380
+
363
381
  #### `get_parent`
364
382
  Get the **parent node**:
365
383
  ```python
@@ -561,8 +579,9 @@ Special thanks to [Mathieu Leplatre](https://blog.mathieu-leplatre.info/pages/ab
561
579
 
562
580
  ## To do
563
581
  Future plans:
564
- * may be will add the ability to determine the priority of the parent by any field, for example, by creation date or alphabetical order;
565
582
  * drug-and-drop support;
583
+ * may be will restore caching;
584
+ * may be will add the ability to determine the priority of the parent by any field, for example, by creation date or alphabetical order;
566
585
  * to be happy, to don't worry, until die.
567
586
 
568
587
 
@@ -1,32 +1,32 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- from django import forms
4
- from .widgets import TreeWidget
5
-
6
-
7
- class TreeNodeForm(forms.ModelForm):
8
-
9
- def __init__(self, *args, **kwargs):
10
-
11
- super(TreeNodeForm, self).__init__(*args, **kwargs)
12
-
13
- if 'tn_parent' not in self.fields:
14
- return
15
- exclude_pks = []
16
- obj = self.instance
17
- if obj.pk:
18
- exclude_pks += [obj.pk]
19
- # tn_get_descendants_pks changed to get_descendants_pks()
20
- # exclude_pks += split_pks(obj.get_descendants_pks())
21
- exclude_pks += obj.get_descendants_pks()
22
-
23
- # Cheaged to "legal" call
24
- manager = obj._meta.model.objects
25
-
26
- self.fields['tn_parent'].queryset = manager.prefetch_related(
27
- 'tn_children').exclude(pk__in=exclude_pks)
28
-
29
- class Meta:
30
- widgets = {
31
- 'tn_parent': TreeWidget(attrs={'style': 'min-width:400px'}),
32
- }
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from django import forms
4
+ from .widgets import TreeWidget
5
+
6
+
7
+ class TreeNodeForm(forms.ModelForm):
8
+
9
+ def __init__(self, *args, **kwargs):
10
+
11
+ super(TreeNodeForm, self).__init__(*args, **kwargs)
12
+
13
+ if 'tn_parent' not in self.fields:
14
+ return
15
+ exclude_pks = []
16
+ obj = self.instance
17
+ if obj.pk:
18
+ exclude_pks += [obj.pk]
19
+ # tn_get_descendants_pks changed to get_descendants_pks()
20
+ # exclude_pks += split_pks(obj.get_descendants_pks())
21
+ exclude_pks += obj.get_descendants_pks()
22
+
23
+ # Cheaged to "legal" call
24
+ manager = obj._meta.model.objects
25
+
26
+ self.fields['tn_parent'].queryset = manager.prefetch_related(
27
+ 'tn_children').exclude(pk__in=exclude_pks)
28
+
29
+ class Meta:
30
+ widgets = {
31
+ 'tn_parent': TreeWidget(attrs={'style': 'min-width:400px'}),
32
+ }
@@ -143,7 +143,6 @@ class TreeNodeModel(with_metaclass(TreeFactory, models.Model)):
143
143
  for c in children
144
144
  ]
145
145
  cls.closure_model.objects.bulk_create(objects)
146
- cls._update_orders()
147
146
 
148
147
  @classmethod
149
148
  def delete_tree(cls):
@@ -189,8 +188,8 @@ class TreeNodeModel(with_metaclass(TreeFactory, models.Model)):
189
188
 
190
189
  qs = self._closure_model.objects.filter(**options).order_by('-depth')
191
190
  select = list(item.parent.pk for item in qs)
192
- resurt = self._meta.model.objects.filter(pk__in=select)
193
- return resurt
191
+ result = self._meta.model.objects.filter(pk__in=select)
192
+ return result
194
193
 
195
194
  @cached_tree_method
196
195
  def get_breadcrumbs(self, attr=None):
@@ -220,7 +219,7 @@ class TreeNodeModel(with_metaclass(TreeFactory, models.Model)):
220
219
  @cached_tree_method
221
220
  def get_children_queryset(self):
222
221
  """Get the children queryset"""
223
- return self._meta.model.objects.filter(tn_paren=self.id)
222
+ return self._meta.model.objects.filter(tn_parent=self.id)
224
223
 
225
224
  def get_depth(self):
226
225
  """Get the node depth (self, how many levels of descendants)"""
@@ -253,7 +252,7 @@ class TreeNodeModel(with_metaclass(TreeFactory, models.Model)):
253
252
  """Get the descendants queryset"""
254
253
 
255
254
  pks = self.get_descendants_pks(include_self, depth)
256
- return self._meta.model.objects.filter(**pks)
255
+ return self._meta.model.objects.filter(pk__in=pks)
257
256
 
258
257
  def get_descendants_tree(self):
259
258
  """Get a n-dimensional dict representing the model tree"""
@@ -655,7 +654,7 @@ class TreeNodeModel(with_metaclass(TreeFactory, models.Model)):
655
654
  try:
656
655
  old = self._meta.model.objects.get(pk=self.pk)
657
656
  old_parent = old.tn_parent
658
- except:
657
+ except self._meta.model.DoesNotExist:
659
658
  force_insert = True
660
659
 
661
660
  super().save(*args, **kwargs)