mirror of
https://github.com/inventree/InvenTree.git
synced 2025-06-18 13:05:42 +00:00
Fix: Treegrid is loading an eternity for huge amounts of data (#3451)
* Added default max depth and lazy loading to StorageLocation * Added default max depth and lazy loading to PartCategory * Update API version * lint: fix * Added INVENTREE_TREE_DEPTH setting * Refactored int conversion into own helper function * Added tests
This commit is contained in:
@ -25,7 +25,8 @@ from company.models import Company, ManufacturerPart, SupplierPart
|
||||
from InvenTree.api import (APIDownloadMixin, AttachmentMixin,
|
||||
ListCreateDestroyAPIView)
|
||||
from InvenTree.filters import InvenTreeOrderingFilter
|
||||
from InvenTree.helpers import DownloadFile, increment, isNull, str2bool
|
||||
from InvenTree.helpers import (DownloadFile, increment, isNull, str2bool,
|
||||
str2int)
|
||||
from InvenTree.mixins import (CreateAPI, ListAPI, ListCreateAPI, RetrieveAPI,
|
||||
RetrieveUpdateAPI, RetrieveUpdateDestroyAPI,
|
||||
UpdateAPI)
|
||||
@ -85,6 +86,8 @@ class CategoryList(ListCreateAPI):
|
||||
|
||||
cascade = str2bool(params.get('cascade', False))
|
||||
|
||||
depth = str2int(params.get('depth', None))
|
||||
|
||||
# Do not filter by category
|
||||
if cat_id is None:
|
||||
pass
|
||||
@ -94,12 +97,18 @@ class CategoryList(ListCreateAPI):
|
||||
if not cascade:
|
||||
queryset = queryset.filter(parent=None)
|
||||
|
||||
if cascade and depth is not None:
|
||||
queryset = queryset.filter(level__lte=depth)
|
||||
|
||||
else:
|
||||
try:
|
||||
category = PartCategory.objects.get(pk=cat_id)
|
||||
|
||||
if cascade:
|
||||
parents = category.get_descendants(include_self=True)
|
||||
if depth is not None:
|
||||
parents = parents.filter(level__lte=category.level + depth)
|
||||
|
||||
parent_ids = [p.id for p in parents]
|
||||
|
||||
queryset = queryset.filter(parent__in=parent_ids)
|
||||
|
@ -49,33 +49,25 @@ class PartCategoryAPITest(InvenTreeAPITestCase):
|
||||
"""Test the PartCategoryList API endpoint"""
|
||||
url = reverse('api-part-category-list')
|
||||
|
||||
response = self.get(url, expected_code=200)
|
||||
test_cases = [
|
||||
({}, 8, 'no parameters'),
|
||||
({'parent': 1, 'cascade': False}, 3, 'Filter by parent, no cascading'),
|
||||
({'parent': 1, 'cascade': True}, 5, 'Filter by parent, cascading'),
|
||||
({'cascade': True, 'depth': 0}, 8, 'Cascade with no parent, depth=0'),
|
||||
({'cascade': False, 'depth': 10}, 8, 'Cascade with no parent, depth=0'),
|
||||
({'parent': 'null', 'cascade': True, 'depth': 0}, 2, 'Cascade with null parent, depth=0'),
|
||||
({'parent': 'null', 'cascade': True, 'depth': 10}, 8, 'Cascade with null parent and bigger depth'),
|
||||
({'parent': 'null', 'cascade': False, 'depth': 10}, 2, 'No cascade even with depth specified with null parent'),
|
||||
({'parent': 1, 'cascade': False, 'depth': 0}, 3, 'Dont cascade with depth=0 and parent'),
|
||||
({'parent': 1, 'cascade': True, 'depth': 0}, 3, 'Cascade with depth=0 and parent'),
|
||||
({'parent': 1, 'cascade': False, 'depth': 1}, 3, 'Dont cascade even with depth=1 specified with parent'),
|
||||
({'parent': 1, 'cascade': True, 'depth': 1}, 5, 'Cascade with depth=1 with parent'),
|
||||
({'parent': 1, 'cascade': True, 'depth': 'abcdefg'}, 5, 'Cascade with invalid depth and parent'),
|
||||
]
|
||||
|
||||
self.assertEqual(len(response.data), 8)
|
||||
|
||||
# Filter by parent, depth=1
|
||||
response = self.get(
|
||||
url,
|
||||
{
|
||||
'parent': 1,
|
||||
'cascade': False,
|
||||
},
|
||||
expected_code=200
|
||||
)
|
||||
|
||||
self.assertEqual(len(response.data), 3)
|
||||
|
||||
# Filter by parent, cascading
|
||||
response = self.get(
|
||||
url,
|
||||
{
|
||||
'parent': 1,
|
||||
'cascade': True,
|
||||
},
|
||||
expected_code=200,
|
||||
)
|
||||
|
||||
self.assertEqual(len(response.data), 5)
|
||||
for params, res_len, description in test_cases:
|
||||
response = self.get(url, params, expected_code=200)
|
||||
self.assertEqual(len(response.data), res_len, description)
|
||||
|
||||
# Check that the required fields are present
|
||||
fields = [
|
||||
@ -90,6 +82,7 @@ class PartCategoryAPITest(InvenTreeAPITestCase):
|
||||
'url'
|
||||
]
|
||||
|
||||
response = self.get(url, expected_code=200)
|
||||
for result in response.data:
|
||||
for f in fields:
|
||||
self.assertIn(f, result)
|
||||
|
Reference in New Issue
Block a user