django-fast-treenode 2.0.5__py3-none-any.whl → 2.0.7__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: django-fast-treenode
3
- Version: 2.0.5
3
+ Version: 2.0.7
4
4
  Summary: Application for supporting tree (hierarchical) data structure in Django projects
5
5
  Home-page: https://github.com/TimurKady/django-fast-treenode
6
6
  Author: Timur Kady
@@ -608,7 +608,7 @@ obj.is_sibling_of(target_obj)
608
608
  ```
609
609
 
610
610
  #### `update_tree`
611
- **Update tree** manually, useful after **bulk updates**:
611
+ **Update tree** manually:
612
612
  ```python
613
613
  cls.update_tree()
614
614
  ```
@@ -622,8 +622,9 @@ In v2.0, the caching mechanism has been improved to prevent excessive memory usa
622
622
  ``` python
623
623
  TREENODE_CACHE_LIMIT = 100
624
624
  ```
625
- **Automatic Management**: In most cases, users don’t need to manually manage cache operations.
626
- **Manual Cache Clearing**:
625
+ **Automatic Management**. In most cases, users don’t need to manually manage cache operations.All methods that somehow change the state of models reset the tree cache automatically.
626
+
627
+ **Manual Cache Clearing**. If for some reason you need to reset the cache, you can do it in two ways:
627
628
  - **Clear cache for a single model**: Use `clear_cache()` at the model level:
628
629
  ```python
629
630
  MyTreeNodeModel.clear_cache()
@@ -1,5 +1,5 @@
1
1
  treenode/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- treenode/admin.py,sha256=x5vJDiZjqcsUAVlK1qkZPK66lQeJq8zYgWwwejentYM,14077
2
+ treenode/admin.py,sha256=ltpCmPCpZpIAOX-ZIuxrleEUvBiUj7AX-jygUjGBHEs,15209
3
3
  treenode/apps.py,sha256=M0O9IKEnJZFfhfz12v4wksYJ-0ECyj1Cy3qXrfywos8,472
4
4
  treenode/cache.py,sha256=Z_FpaS0vTKXqAI4n1QkZ7A_ILsLU3Q8rLgerA6pYyAA,7210
5
5
  treenode/forms.py,sha256=imoLzr7qFlOBdeMQK12rAFp6hINpe0PS_U4-V8RRcDU,2802
@@ -30,12 +30,12 @@ treenode/templates/admin/tree_node_export.html,sha256=vJxEoGI-US6VdFddxAFgL5r3Mg
30
30
  treenode/templates/admin/tree_node_import.html,sha256=ZFoveJ08X99EGiwFCfQowXI9oS9VgcFtRLYVDIWq-Fg,969
31
31
  treenode/templates/widgets/tree_widget.css,sha256=2bEaxu1x7QJZ7erbs2SLMaxeaiMkjQXadfcDEW8wfok,551
32
32
  treenode/templates/widgets/tree_widget.html,sha256=GKcCU-B2FkkJ2BSOuXOw9e_PdYTtADcvyITEXqOlZ9Y,723
33
- treenode/utils/__init__.py,sha256=jAVT-uNGQDKPVq5ET4JE2GhRpzbxFdHU25w9sLC3_To,134
33
+ treenode/utils/__init__.py,sha256=FP7DszaIC3Xzw-7P4Q8Mc2dtQgJnIVioN9ZCbvQxw0w,322
34
34
  treenode/utils/base36.py,sha256=ydgu9hqDaK-WyS8zG-mtSWo7hJqbB4iHqkGz4-IVrb4,834
35
35
  treenode/utils/exporter.py,sha256=l-IEsk2fK8xe-E-Hi7SMOV7ZIwxM6mZih5-0rhvsx9E,5396
36
36
  treenode/utils/importer.py,sha256=n23PBFPXN-6S_Dl8Qmx56sp0eLy_lWfpxrzJqwygQf0,14190
37
- django_fast_treenode-2.0.5.dist-info/LICENSE,sha256=GiiEe4Y9oOCbn9eGuNew1mMYHU_bJWaCK9zOusnKvvU,1091
38
- django_fast_treenode-2.0.5.dist-info/METADATA,sha256=sjucboSzhcI6bto4f0rvLjtKk2c5-2qQwohYSOQJWsc,23109
39
- django_fast_treenode-2.0.5.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
40
- django_fast_treenode-2.0.5.dist-info/top_level.txt,sha256=fmgxHbXyx1O2MPi_9kjx8aL9L-8TmV0gre4Go8XgqFk,9
41
- django_fast_treenode-2.0.5.dist-info/RECORD,,
37
+ django_fast_treenode-2.0.7.dist-info/LICENSE,sha256=GiiEe4Y9oOCbn9eGuNew1mMYHU_bJWaCK9zOusnKvvU,1091
38
+ django_fast_treenode-2.0.7.dist-info/METADATA,sha256=WzpmDNemaE62W7rLqF857L5VxhfPe5hVuS27UdJ9GDM,23242
39
+ django_fast_treenode-2.0.7.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
40
+ django_fast_treenode-2.0.7.dist-info/top_level.txt,sha256=fmgxHbXyx1O2MPi_9kjx8aL9L-8TmV0gre4Go8XgqFk,9
41
+ django_fast_treenode-2.0.7.dist-info/RECORD,,
treenode/admin.py CHANGED
@@ -6,7 +6,7 @@ This module provides Django admin integration for the TreeNode model.
6
6
  It includes custom tree-based sorting, optimized queries, and
7
7
  import/export functionality for hierarchical data structures.
8
8
 
9
- Version: 2.0.0
9
+ Version: 2.0.6
10
10
  Author: Timur Kady
11
11
  Email: kaduevtr@gmail.com
12
12
  """
@@ -81,7 +81,7 @@ class TreeNodeAdminModel(admin.ModelAdmin):
81
81
  TREENODE_DISPLAY_MODE_INDENTATION = 'indentation'
82
82
 
83
83
  treenode_display_mode = TREENODE_DISPLAY_MODE_ACCORDION
84
-
84
+ import_export = False # Track import/export availability
85
85
  change_list_template = "admin/tree_node_changelist.html"
86
86
  ordering = []
87
87
  list_per_page = 1000
@@ -107,10 +107,25 @@ class TreeNodeAdminModel(admin.ModelAdmin):
107
107
  """Динамически добавляем поле `tn_order` в `list_display`."""
108
108
  super().__init__(model, admin_site)
109
109
 
110
- # Если `list_display` пустой, берем все `fields`
110
+ # If `list_display` is empty, take all `fields`
111
111
  if not self.list_display:
112
112
  self.list_display = [field.name for field in model._meta.fields]
113
113
 
114
+ # Check for necessary dependencies
115
+ self.import_export = all(
116
+ importlib.util.find_spec(pkg) is not None
117
+ for pkg in ["openpyxl", "pyyaml", "pandas"]
118
+ )
119
+
120
+ if self.import_export:
121
+ from .utils import TreeNodeImporter, TreeNodeExporter
122
+
123
+ self.TreeNodeImporter = TreeNodeImporter
124
+ self.TreeNodeExporter = TreeNodeExporter
125
+ else:
126
+ self.TreeNodeImporter = None
127
+ self.TreeNodeExporter = None
128
+
114
129
  def get_queryset(self, request):
115
130
  """Override get_ueryset()."""
116
131
  queryset = super().get_queryset(request)
@@ -182,10 +197,7 @@ class TreeNodeAdminModel(admin.ModelAdmin):
182
197
  def changelist_view(self, request, extra_context=None):
183
198
  """Changelist View."""
184
199
  extra_context = extra_context or {}
185
- extra_context['import_export_enabled'] = all(
186
- importlib.util.find_spec(pkg)
187
- is not None for pkg in ["openpyxl", "pyyaml", "pandas"]
188
- )
200
+ extra_context['import_export_enabled'] = self.import_export
189
201
  return super().changelist_view(request, extra_context=extra_context)
190
202
 
191
203
  def get_ordering(self, request):
@@ -250,12 +262,19 @@ class TreeNodeAdminModel(admin.ModelAdmin):
250
262
  return form
251
263
 
252
264
  def get_urls(self):
253
- """Extend admin URLs with custom import/export routes."""
265
+ """
266
+ Extend admin URLs with custom import/export routes.
267
+
268
+ Register these URLs only if all the required packages are installed.
269
+ """
254
270
  urls = super().get_urls()
255
- custom_urls = [
256
- path('import/', self.import_view, name='tree_node_import'),
257
- path('export/', self.export_view, name='tree_node_export'),
258
- ]
271
+ if self.import_export:
272
+ custom_urls = [
273
+ path('import/', self.import_view, name='tree_node_import'),
274
+ path('export/', self.export_view, name='tree_node_export'),
275
+ ]
276
+ else:
277
+ custom_urls = []
259
278
  return custom_urls + urls
260
279
 
261
280
  def import_view(self, request):
@@ -265,6 +284,14 @@ class TreeNodeAdminModel(admin.ModelAdmin):
265
284
  File upload processing, auto-detection of format, validation and data
266
285
  import.
267
286
  """
287
+ if not self.import_export:
288
+ self.message_user(
289
+ request,
290
+ "Import functionality is disabled because required \
291
+ packages are not installed."
292
+ )
293
+ return redirect("..")
294
+
268
295
  if request.method == 'POST':
269
296
  if 'file' not in request.FILES:
270
297
  return render(
@@ -317,6 +344,14 @@ class TreeNodeAdminModel(admin.ModelAdmin):
317
344
  link for manual download,
318
345
  and a button to go to the model page.
319
346
  """
347
+ if not self.import_export:
348
+ self.message_user(
349
+ request,
350
+ "Export functionality is disabled because required \
351
+ packages are not installed."
352
+ )
353
+ return redirect("..")
354
+
320
355
  # If the download parameter is present, we give the file directly
321
356
  if 'download' in request.GET:
322
357
  # Get file format
@@ -1,4 +1,14 @@
1
- from .exporter import TreeNodeExporter
2
- from .importer import TreeNodeImporter
1
+ import importlib.util
2
+
3
+ extra = all(
4
+ importlib.util.find_spec(pkg) is not None
5
+ for pkg in ["openpyxl", "pyyaml", "pandas"]
6
+ )
7
+
8
+ if extra:
9
+ from .exporter import TreeNodeExporter
10
+ from .importer import TreeNodeImporter
11
+ __all__ = ["TreeNodeExporter", "TreeNodeImporter"]
12
+ else:
13
+ __all__ = []
3
14
 
4
- __all__ = ["TreeNodeExporter", "TreeNodeImporter"]