diff --git a/InvenTree/part/api.py b/InvenTree/part/api.py index bcbd5bf41a..f776c208b5 100644 --- a/InvenTree/part/api.py +++ b/InvenTree/part/api.py @@ -239,7 +239,7 @@ class PartList(generics.ListCreateAPIView): cat_id = part['category'] if cat_id is not None: - category_ids.add(part['category']) + category_ids.add(cat_id) # Fetch only the required PartCategory objects from the database categories = PartCategory.objects.filter(pk__in=category_ids).prefetch_related( @@ -258,7 +258,7 @@ class PartList(generics.ListCreateAPIView): cat_id = part['category'] if cat_id is not None and cat_id in category_map.keys(): - detail = category_map[part['category']] + detail = category_map[cat_id] else: detail = None diff --git a/InvenTree/stock/api.py b/InvenTree/stock/api.py index c31c1b8993..d1f6c2d944 100644 --- a/InvenTree/stock/api.py +++ b/InvenTree/stock/api.py @@ -15,7 +15,7 @@ from .models import StockItemTracking from part.models import Part, PartCategory from .serializers import StockItemSerializer -from .serializers import LocationSerializer +from .serializers import LocationSerializer, LocationBriefSerializer from .serializers import StockTrackingSerializer from InvenTree.views import TreeSerializer @@ -332,11 +332,6 @@ class StockList(generics.ListCreateAPIView): except AttributeError: pass - try: - kwargs['location_detail'] = str2bool(self.request.query_params.get('location_detail', None)) - except AttributeError: - pass - try: kwargs['supplier_part_detail'] = str2bool(self.request.query_params.get('supplier_part_detail', None)) except AttributeError: @@ -350,6 +345,62 @@ class StockList(generics.ListCreateAPIView): # TODO - Override the 'create' method for this view, # to allow the user to be recorded when a new StockItem object is created + def list(self, request, *args, **kwargs): + """ + Override the 'list' method, as the StockLocation objects + are very expensive to serialize. + + So, we fetch and serialize the required StockLocation objects only as required. + """ + + queryset = self.filter_queryset(self.get_queryset()) + + page = self.paginate_queryset(queryset) + if page is not None: + serializer = self.get_serializer(page, many=True) + return self.get_paginated_response(serializer.data) + + serializer = self.get_serializer(queryset, many=True) + + data = serializer.data + + # Do we wish to include StockLocation detail? + if str2bool(request.query_params.get('location_detail', False)): + + # Work out which locations we need to query + location_ids = set() + + for stock_item in data: + loc_id = stock_item['location'] + + if loc_id is not None: + location_ids.add(loc_id) + + # Fetch only the required StockLocation objects from the database + locations = StockLocation.objects.filter(pk__in=location_ids).prefetch_related( + 'parent', + 'children', + ) + + location_map = {} + + # Serialize each StockLocation object + for location in locations: + location_map[location.pk] = LocationBriefSerializer(location).data + + # Now update each StockItem with the related StockLocation data + for stock_item in data: + loc_id = stock_item['location'] + + if loc_id is not None and loc_id in location_map.keys(): + detail = location_map[loc_id] + else: + detail = None + + stock_item['location_detail'] = detail + + return Response(data) + def get_queryset(self, *args, **kwargs): queryset = super().get_queryset(*args, **kwargs) diff --git a/InvenTree/stock/serializers.py b/InvenTree/stock/serializers.py index 4e586b789e..eeab49eb4b 100644 --- a/InvenTree/stock/serializers.py +++ b/InvenTree/stock/serializers.py @@ -17,15 +17,12 @@ class LocationBriefSerializer(InvenTreeModelSerializer): Provides a brief serializer for a StockLocation object """ - url = serializers.CharField(source='get_absolute_url', read_only=True) - class Meta: model = StockLocation fields = [ 'pk', 'name', 'pathstring', - 'url', ]