2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-07-13 08:21:26 +00:00

Major major major (improvements for StockItem list API)

OK LISTEN UP - Lots of work went into making this speedier:

- For related detail fields (e.g. part_detail), we pre-fetch and cache the model data
- This eliminates duplicate database hits for the same model instances
- Perform all field filtering manually, rather than using the DRF 'filter_fields' concept (this seems to add a lot of overhead)
- Use query annotations to getch calculated fields rather than fetching one-at-a-time
- And finally, if the request is AJAX then return a JsonResponse which is SO FREAKING MUCH FASTER
This commit is contained in:
Oliver Walters
2020-05-02 13:46:19 +10:00
parent 44319d24e4
commit 4197e29fce
3 changed files with 134 additions and 66 deletions

View File

@ -7,6 +7,9 @@ from rest_framework import serializers
from .models import StockItem, StockLocation
from .models import StockItemTracking
from django.db.models import Sum, Count
from django.db.models.functions import Coalesce
from company.serializers import SupplierPartSerializer
from part.serializers import PartBriefSerializer
from InvenTree.serializers import UserSerializerBrief, InvenTreeModelSerializer
@ -62,6 +65,10 @@ class StockItemSerializer(InvenTreeModelSerializer):
"""
return queryset.prefetch_related(
'belongs_to',
'build',
'build_order',
'sales_order',
'supplier_part',
'supplier_part__supplier',
'supplier_part__manufacturer',
@ -79,7 +86,13 @@ class StockItemSerializer(InvenTreeModelSerializer):
performing database queries as efficiently as possible.
"""
# TODO - Add custom annotated fields
queryset = queryset.annotate(
allocated = Coalesce(
Sum('sales_order_allocations__quantity', distinct=True), 0) + Coalesce(
Sum('allocations__quantity', distinct=True), 0),
tracking_items = Count('tracking_info'),
)
return queryset
status_text = serializers.CharField(source='get_status_display', read_only=True)
@ -88,10 +101,10 @@ class StockItemSerializer(InvenTreeModelSerializer):
location_detail = LocationBriefSerializer(source='location', many=False, read_only=True)
supplier_part_detail = SupplierPartSerializer(source='supplier_part', many=False, read_only=True)
tracking_items = serializers.IntegerField(source='tracking_info_count', read_only=True)
tracking_items = serializers.IntegerField()
quantity = serializers.FloatField()
allocated = serializers.FloatField(source='allocation_count', read_only=True)
allocated = serializers.FloatField()
def __init__(self, *args, **kwargs):
@ -140,6 +153,7 @@ class StockItemSerializer(InvenTreeModelSerializer):
They can be updated by accessing the appropriate API endpoints
"""
read_only_fields = [
'allocated',
'stocktake_date',
'stocktake_user',
'updated',