2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-07-01 03:00:54 +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:
luwol03
2022-08-05 00:07:12 +02:00
committed by GitHub
parent a2c2d1d0a4
commit a9e22d0ae9
10 changed files with 225 additions and 36 deletions

View File

@ -26,7 +26,7 @@ from InvenTree.api import (APIDownloadMixin, AttachmentMixin,
ListCreateDestroyAPIView)
from InvenTree.filters import InvenTreeOrderingFilter
from InvenTree.helpers import (DownloadFile, extract_serial_numbers, isNull,
str2bool)
str2bool, str2int)
from InvenTree.mixins import (CreateAPI, ListAPI, ListCreateAPI, RetrieveAPI,
RetrieveUpdateAPI, RetrieveUpdateDestroyAPI)
from order.models import PurchaseOrder, SalesOrder, SalesOrderAllocation
@ -241,6 +241,8 @@ class StockLocationList(ListCreateAPI):
cascade = str2bool(params.get('cascade', False))
depth = str2int(params.get('depth', None))
# Do not filter by location
if loc_id is None:
pass
@ -251,6 +253,9 @@ class StockLocationList(ListCreateAPI):
if not cascade:
queryset = queryset.filter(parent=None)
if cascade and depth is not None:
queryset = queryset.filter(level__lte=depth)
else:
try:
@ -259,6 +264,9 @@ class StockLocationList(ListCreateAPI):
# All sub-locations to be returned too?
if cascade:
parents = location.get_descendants(include_self=True)
if depth is not None:
parents = parents.filter(level__lte=location.level + depth)
parent_ids = [p.id for p in parents]
queryset = queryset.filter(parent__in=parent_ids)

View File

@ -54,11 +54,44 @@ class StockLocationTest(StockAPITestCase):
StockLocation.objects.create(name='top', description='top category')
def test_list(self):
"""Test StockLocation list."""
# Check that we can request the StockLocation list
response = self.client.get(self.list_url, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertGreaterEqual(len(response.data), 1)
"""Test the StockLocationList API endpoint"""
test_cases = [
({}, 8, 'no parameters'),
({'parent': 1, 'cascade': False}, 2, 'Filter by parent, no cascading'),
({'parent': 1, 'cascade': True}, 2, '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}, 7, '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}, 3, 'No cascade even with depth specified with null parent'),
({'parent': 1, 'cascade': False, 'depth': 0}, 2, 'Dont cascade with depth=0 and parent'),
({'parent': 1, 'cascade': True, 'depth': 0}, 2, 'Cascade with depth=0 and parent'),
({'parent': 1, 'cascade': False, 'depth': 1}, 2, 'Dont cascade even with depth=1 specified with parent'),
({'parent': 1, 'cascade': True, 'depth': 1}, 2, 'Cascade with depth=1 with parent'),
({'parent': 1, 'cascade': True, 'depth': 'abcdefg'}, 2, 'Cascade with invalid depth and parent'),
]
for params, res_len, description in test_cases:
response = self.get(self.list_url, params, expected_code=200)
self.assertEqual(len(response.data), res_len, description)
# Check that the required fields are present
fields = [
'pk',
'name',
'description',
'level',
'parent',
'items',
'pathstring',
'owner',
'url'
]
response = self.get(self.list_url, expected_code=200)
for result in response.data:
for f in fields:
self.assertIn(f, result)
def test_add(self):
"""Test adding StockLocation."""