Custom list serializer for 'location_detail'

This commit is contained in:
Oliver Walters 2020-05-02 10:05:35 +10:00
parent a537b6df6e
commit 44319d24e4
3 changed files with 59 additions and 11 deletions

View File

@ -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

View File

@ -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)

View File

@ -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',
]