mirror of
https://github.com/inventree/InvenTree.git
synced 2025-07-01 03:00:54 +00:00
Improve StockItem API speed (#5042)
- Removes child detail fields which cannot be effectively annotated - Prefetch required fields - Add unit test method for checking query count
This commit is contained in:
@ -795,15 +795,6 @@ class StockList(APIDownloadMixin, ListCreateDestroyAPIView):
|
||||
|
||||
queryset = StockSerializers.StockItemSerializer.annotate_queryset(queryset)
|
||||
|
||||
# Also ensure that we pre-fecth all the related items
|
||||
queryset = queryset.prefetch_related(
|
||||
'part',
|
||||
'part__category',
|
||||
'location',
|
||||
'test_results',
|
||||
'tags',
|
||||
)
|
||||
|
||||
return queryset
|
||||
|
||||
def filter_queryset(self, queryset):
|
||||
|
@ -231,10 +231,17 @@ class StockItemSerializer(InvenTree.serializers.InvenTreeTagModelSerializer):
|
||||
"""Add some extra annotations to the queryset, performing database queries as efficiently as possible."""
|
||||
|
||||
queryset = queryset.prefetch_related(
|
||||
'location',
|
||||
'sales_order',
|
||||
'purchase_order',
|
||||
'part',
|
||||
'part__category',
|
||||
'part__pricing_data',
|
||||
'supplier_part',
|
||||
'supplier_part__manufacturer_part',
|
||||
'supplier_part__tags',
|
||||
'test_results',
|
||||
'tags',
|
||||
)
|
||||
|
||||
# Annotate the queryset with the total allocated to sales orders
|
||||
@ -280,7 +287,7 @@ class StockItemSerializer(InvenTree.serializers.InvenTreeTagModelSerializer):
|
||||
status_text = serializers.CharField(source='get_status_display', read_only=True)
|
||||
|
||||
# Optional detail fields, which can be appended via query parameters
|
||||
supplier_part_detail = SupplierPartSerializer(source='supplier_part', many=False, read_only=True)
|
||||
supplier_part_detail = SupplierPartSerializer(source='supplier_part', supplier_detail=False, manufacturer_detail=False, part_detail=False, many=False, read_only=True)
|
||||
part_detail = PartBriefSerializer(source='part', many=False, read_only=True)
|
||||
location_detail = LocationBriefSerializer(source='location', many=False, read_only=True)
|
||||
tests = StockItemTestResultSerializer(source='test_results', many=True, read_only=True)
|
||||
|
@ -557,6 +557,42 @@ class StockItemListTest(StockAPITestCase):
|
||||
|
||||
self.assertEqual(len(dataset), 17)
|
||||
|
||||
def test_query_count(self):
|
||||
"""Test that the number of queries required to fetch stock items is reasonable."""
|
||||
|
||||
def get_stock(data):
|
||||
"""Helper function to fetch stock items."""
|
||||
response = self.client.get(self.list_url, data=data)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
return response.data
|
||||
|
||||
# Create a bunch of StockItem objects
|
||||
prt = Part.objects.first()
|
||||
|
||||
StockItem.objects.bulk_create([
|
||||
StockItem(
|
||||
part=prt,
|
||||
quantity=1,
|
||||
level=0, tree_id=0, lft=0, rght=0,
|
||||
) for _ in range(100)
|
||||
])
|
||||
|
||||
# List *all* stock items
|
||||
with self.assertNumQueriesLessThan(25):
|
||||
get_stock({})
|
||||
|
||||
# List all stock items, with part detail
|
||||
with self.assertNumQueriesLessThan(20):
|
||||
get_stock({'part_detail': True})
|
||||
|
||||
# List all stock items, with supplier_part detail
|
||||
with self.assertNumQueriesLessThan(20):
|
||||
get_stock({'supplier_part_detail': True})
|
||||
|
||||
# List all stock items, with 'location' and 'tests' detail
|
||||
with self.assertNumQueriesLessThan(20):
|
||||
get_stock({'location_detail': True, 'tests': True})
|
||||
|
||||
|
||||
class StockItemTest(StockAPITestCase):
|
||||
"""Series of API tests for the StockItem API."""
|
||||
|
Reference in New Issue
Block a user