mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Significant increase in query speed for Part list
- Custom list method - Cache PartCategory objects in memory
This commit is contained in:
parent
acea0d6e92
commit
4a60da67fd
@ -110,7 +110,7 @@ class PartThumbs(generics.ListAPIView):
|
|||||||
|
|
||||||
serializer_class = part_serializers.PartThumbSerializer
|
serializer_class = part_serializers.PartThumbSerializer
|
||||||
|
|
||||||
def list(self, reguest, *args, **kwargs):
|
def list(self, request, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
Serialize the available Part images.
|
Serialize the available Part images.
|
||||||
- Images may be used for multiple parts!
|
- Images may be used for multiple parts!
|
||||||
@ -142,6 +142,7 @@ class PartDetail(generics.RetrieveUpdateAPIView):
|
|||||||
|
|
||||||
queryset = part_serializers.PartSerializer.prefetch_queryset(queryset)
|
queryset = part_serializers.PartSerializer.prefetch_queryset(queryset)
|
||||||
queryset = part_serializers.PartSerializer.annotate_queryset(queryset)
|
queryset = part_serializers.PartSerializer.annotate_queryset(queryset)
|
||||||
|
|
||||||
return queryset
|
return queryset
|
||||||
|
|
||||||
permission_classes = [
|
permission_classes = [
|
||||||
@ -151,15 +152,13 @@ class PartDetail(generics.RetrieveUpdateAPIView):
|
|||||||
def get_serializer(self, *args, **kwargs):
|
def get_serializer(self, *args, **kwargs):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
cat_detail = str2bool(self.request.query_params.get('category_detail', False))
|
kwargs['category_detail'] = str2bool(self.request.query_params.get('category_detail', False))
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
cat_detail = None
|
pass
|
||||||
|
|
||||||
# Ensure the request context is passed through
|
# Ensure the request context is passed through
|
||||||
kwargs['context'] = self.get_serializer_context()
|
kwargs['context'] = self.get_serializer_context()
|
||||||
|
|
||||||
kwargs['category_detail'] = cat_detail
|
|
||||||
|
|
||||||
# Pass a list of "starred" parts fo the current user to the serializer
|
# Pass a list of "starred" parts fo the current user to the serializer
|
||||||
# We do this to reduce the number of database queries required!
|
# We do this to reduce the number of database queries required!
|
||||||
if self.starred_parts is None and self.request is not None:
|
if self.starred_parts is None and self.request is not None:
|
||||||
@ -206,8 +205,6 @@ class PartList(generics.ListCreateAPIView):
|
|||||||
# Ensure the request context is passed through
|
# Ensure the request context is passed through
|
||||||
kwargs['context'] = self.get_serializer_context()
|
kwargs['context'] = self.get_serializer_context()
|
||||||
|
|
||||||
kwargs['category_detail'] = cat_detail
|
|
||||||
|
|
||||||
# Pass a list of "starred" parts fo the current user to the serializer
|
# Pass a list of "starred" parts fo the current user to the serializer
|
||||||
# We do this to reduce the number of database queries required!
|
# We do this to reduce the number of database queries required!
|
||||||
if self.starred_parts is None and self.request is not None:
|
if self.starred_parts is None and self.request is not None:
|
||||||
@ -217,6 +214,63 @@ class PartList(generics.ListCreateAPIView):
|
|||||||
|
|
||||||
return self.serializer_class(*args, **kwargs)
|
return self.serializer_class(*args, **kwargs)
|
||||||
|
|
||||||
|
def list(self, request, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Overide the 'list' method, as the PartCategory objects are
|
||||||
|
very expensive to serialize!
|
||||||
|
|
||||||
|
So we will serialize them first, and keep them in memory,
|
||||||
|
so that they do not have to be serialized multiple times...
|
||||||
|
"""
|
||||||
|
|
||||||
|
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 PartCategory detail?
|
||||||
|
if str2bool(request.query_params.get('category_detail', False)):
|
||||||
|
|
||||||
|
# Work out which part categorie we need to query
|
||||||
|
category_ids = set()
|
||||||
|
|
||||||
|
for part in data:
|
||||||
|
cat_id = part['category']
|
||||||
|
|
||||||
|
if cat_id is not None:
|
||||||
|
category_ids.add(part['category'])
|
||||||
|
|
||||||
|
# Fetch only the required PartCategory objects from the database
|
||||||
|
categories = PartCategory.objects.filter(pk__in=category_ids).prefetch_related(
|
||||||
|
'parts',
|
||||||
|
'parent',
|
||||||
|
'children',
|
||||||
|
)
|
||||||
|
|
||||||
|
category_map = {}
|
||||||
|
|
||||||
|
# Serialize each PartCategory object
|
||||||
|
for category in categories:
|
||||||
|
category_map[category.pk] = part_serializers.CategorySerializer(category).data
|
||||||
|
|
||||||
|
for part in data:
|
||||||
|
cat_id = part['category']
|
||||||
|
|
||||||
|
if cat_id is not None and cat_id in category_map.keys():
|
||||||
|
detail = category_map[part['category']]
|
||||||
|
else:
|
||||||
|
detail = None
|
||||||
|
|
||||||
|
part['category_detail'] = detail
|
||||||
|
|
||||||
|
return Response(data)
|
||||||
|
|
||||||
def create(self, request, *args, **kwargs):
|
def create(self, request, *args, **kwargs):
|
||||||
""" Override the default 'create' behaviour:
|
""" Override the default 'create' behaviour:
|
||||||
We wish to save the user who created this part!
|
We wish to save the user who created this part!
|
||||||
|
@ -101,6 +101,8 @@ class PartSerializer(InvenTreeModelSerializer):
|
|||||||
|
|
||||||
return queryset.prefetch_related(
|
return queryset.prefetch_related(
|
||||||
'category',
|
'category',
|
||||||
|
'category__parts',
|
||||||
|
'category__parent',
|
||||||
'stock_items',
|
'stock_items',
|
||||||
'bom_items',
|
'bom_items',
|
||||||
'builds',
|
'builds',
|
||||||
|
Loading…
Reference in New Issue
Block a user