mirror of
https://github.com/inventree/InvenTree.git
synced 2025-12-17 17:58:22 +00:00
[refactor] Optional prefetch (#11012)
* Automatic prefetch of related fields for enable_filter - Allows us to *not* prefetch fields (expensive) when they are not going to be used - Enables re-usable components for common detail fields * Refactor "project_code_detail" filter into common component - Automatically apply correct prefetch fields * Refactor 'parameters' annotation - add 'enable_parameters_filter' function - Prefetch parameters only when needed - Refactor / consolidate code * Refactor SupplierPartSerializer - Make fields switchable - Ensure correct prefetch_related * Refactor serializer for ManufacturerPart * Refactor BuildSerializer * Refactor PurchaseOrderSerializer * Refactor SalesOrderSerializer * Refactor ReturnOrderSerializer * Remove debug statements * Tweaks * Simplify custom filterable fields * Bump API version * Fix for data export * Additional unit tests * Remove unused "prefetch_func" option * Refactor PurchaseOrderLineItemList * Refactor SalesOrderLineItemList * Refactor ReturnOrderLineItem * Cleanup "pretty_name" * Fix for build list * Refactoring StockItem API endpoint - Needs significant work still * Refactoring for BuildLineSerializer * Keep all optional fields when exporting data * Improve "UserRoles" API endpoint - Prefetch roles - Prevents significant number of db hits * Prefetch Parameter API list * Bug fix for exporting logic * Specify InvenTreeOutputOption * Optional prefetch for primary_address * Fix typing * Fix unit test * fixes for playwright tests * Update Part API - Improved prefetching * Fix for prefetch
This commit is contained in:
@@ -10,7 +10,7 @@ from rest_framework import serializers
|
||||
from sql_util.utils import SubqueryCount
|
||||
from taggit.serializers import TagListSerializerField
|
||||
|
||||
import common.serializers
|
||||
import common.filters
|
||||
import company.filters
|
||||
import part.filters
|
||||
import part.serializers as part_serializers
|
||||
@@ -163,22 +163,19 @@ class CompanySerializer(
|
||||
|
||||
queryset = queryset.annotate(parts_supplied=SubqueryCount('supplied_parts'))
|
||||
|
||||
queryset = queryset.prefetch_related(
|
||||
return queryset
|
||||
|
||||
primary_address = enable_filter(
|
||||
AddressBriefSerializer(read_only=True, allow_null=True),
|
||||
False,
|
||||
filter_name='address_detail',
|
||||
prefetch_fields=[
|
||||
Prefetch(
|
||||
'addresses',
|
||||
queryset=Address.objects.filter(primary=True),
|
||||
to_attr='primary_address_list',
|
||||
)
|
||||
)
|
||||
|
||||
queryset = Company.annotate_parameters(queryset)
|
||||
|
||||
return queryset
|
||||
|
||||
primary_address = enable_filter(
|
||||
AddressBriefSerializer(read_only=True, allow_null=True),
|
||||
True,
|
||||
filter_name='address_detail',
|
||||
],
|
||||
)
|
||||
|
||||
image = InvenTreeImageSerializerField(required=False, allow_null=True)
|
||||
@@ -195,11 +192,7 @@ class CompanySerializer(
|
||||
help_text=_('Default currency used for this supplier'), required=True
|
||||
)
|
||||
|
||||
parameters = enable_filter(
|
||||
common.serializers.ParameterSerializer(many=True, read_only=True),
|
||||
False,
|
||||
filter_name='parameters',
|
||||
)
|
||||
parameters = common.filters.enable_parameters_filter()
|
||||
|
||||
def save(self):
|
||||
"""Save the Company instance."""
|
||||
@@ -269,24 +262,14 @@ class ManufacturerPartSerializer(
|
||||
|
||||
tags = TagListSerializerField(required=False)
|
||||
|
||||
parameters = enable_filter(
|
||||
common.serializers.ParameterSerializer(many=True, read_only=True),
|
||||
False,
|
||||
filter_name='parameters',
|
||||
)
|
||||
parameters = common.filters.enable_parameters_filter()
|
||||
|
||||
part_detail = enable_filter(
|
||||
part_serializers.PartBriefSerializer(
|
||||
source='part', many=False, read_only=True, allow_null=True
|
||||
),
|
||||
True,
|
||||
)
|
||||
|
||||
manufacturer_detail = enable_filter(
|
||||
CompanyBriefSerializer(
|
||||
source='manufacturer', many=False, read_only=True, allow_null=True
|
||||
),
|
||||
True,
|
||||
prefetch_fields=['part'],
|
||||
)
|
||||
|
||||
pretty_name = enable_filter(
|
||||
@@ -297,6 +280,14 @@ class ManufacturerPartSerializer(
|
||||
queryset=Company.objects.filter(is_manufacturer=True)
|
||||
)
|
||||
|
||||
manufacturer_detail = enable_filter(
|
||||
CompanyBriefSerializer(
|
||||
source='manufacturer', many=False, read_only=True, allow_null=True
|
||||
),
|
||||
True,
|
||||
prefetch_fields=['manufacturer'],
|
||||
)
|
||||
|
||||
|
||||
class SupplierPriceBreakBriefSerializer(
|
||||
FilterableSerializerMixin, InvenTreeModelSerializer
|
||||
@@ -399,33 +390,13 @@ class SupplierPartSerializer(
|
||||
# Check if 'available' quantity was supplied
|
||||
self.has_available_quantity = 'available' in kwargs.get('data', {})
|
||||
|
||||
# TODO INVE-T1 support complex filters
|
||||
brief = kwargs.pop('brief', False)
|
||||
detail_default = not brief
|
||||
part_detail = kwargs.pop('part_detail', detail_default)
|
||||
supplier_detail = kwargs.pop('supplier_detail', detail_default)
|
||||
manufacturer_detail = kwargs.pop('manufacturer_detail', detail_default)
|
||||
|
||||
prettify = kwargs.pop('pretty', False)
|
||||
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
if isGeneratingSchema():
|
||||
return
|
||||
|
||||
if part_detail is not True:
|
||||
self.fields.pop('part_detail', None)
|
||||
|
||||
if supplier_detail is not True:
|
||||
self.fields.pop('supplier_detail', None)
|
||||
|
||||
if manufacturer_detail is not True:
|
||||
self.fields.pop('manufacturer_detail', None)
|
||||
self.fields.pop('manufacturer_part_detail', None)
|
||||
|
||||
if brief or prettify is not True:
|
||||
self.fields.pop('pretty_name', None)
|
||||
|
||||
if brief:
|
||||
self.fields.pop('tags')
|
||||
self.fields.pop('available')
|
||||
@@ -455,46 +426,61 @@ class SupplierPartSerializer(
|
||||
),
|
||||
False,
|
||||
filter_name='price_breaks',
|
||||
prefetch_fields=['pricebreaks'],
|
||||
)
|
||||
|
||||
parameters = enable_filter(
|
||||
common.serializers.ParameterSerializer(many=True, read_only=True),
|
||||
parameters = common.filters.enable_parameters_filter()
|
||||
|
||||
part_detail = enable_filter(
|
||||
part_serializers.PartBriefSerializer(
|
||||
label=_('Part'), source='part', many=False, read_only=True, allow_null=True
|
||||
),
|
||||
False,
|
||||
filter_name='parameters',
|
||||
prefetch_fields=['part'],
|
||||
)
|
||||
|
||||
part_detail = part_serializers.PartBriefSerializer(
|
||||
label=_('Part'), source='part', many=False, read_only=True, allow_null=True
|
||||
supplier_detail = enable_filter(
|
||||
CompanyBriefSerializer(
|
||||
label=_('Supplier'),
|
||||
source='supplier',
|
||||
many=False,
|
||||
read_only=True,
|
||||
allow_null=True,
|
||||
),
|
||||
False,
|
||||
prefetch_fields=['supplier'],
|
||||
)
|
||||
|
||||
supplier_detail = CompanyBriefSerializer(
|
||||
label=_('Supplier'),
|
||||
source='supplier',
|
||||
many=False,
|
||||
read_only=True,
|
||||
allow_null=True,
|
||||
manufacturer_detail = enable_filter(
|
||||
CompanyBriefSerializer(
|
||||
label=_('Manufacturer'),
|
||||
source='manufacturer_part.manufacturer',
|
||||
many=False,
|
||||
read_only=True,
|
||||
allow_null=True,
|
||||
),
|
||||
False,
|
||||
prefetch_fields=['manufacturer_part__manufacturer'],
|
||||
)
|
||||
|
||||
manufacturer_detail = CompanyBriefSerializer(
|
||||
label=_('Manufacturer'),
|
||||
source='manufacturer_part.manufacturer',
|
||||
many=False,
|
||||
read_only=True,
|
||||
allow_null=True,
|
||||
pretty_name = enable_filter(
|
||||
FilterableCharField(read_only=True, allow_null=True), filter_name='pretty'
|
||||
)
|
||||
|
||||
pretty_name = serializers.CharField(read_only=True, allow_null=True)
|
||||
|
||||
supplier = serializers.PrimaryKeyRelatedField(
|
||||
label=_('Supplier'), queryset=Company.objects.filter(is_supplier=True)
|
||||
)
|
||||
|
||||
manufacturer_part_detail = ManufacturerPartSerializer(
|
||||
label=_('Manufacturer Part'),
|
||||
source='manufacturer_part',
|
||||
part_detail=False,
|
||||
read_only=True,
|
||||
allow_null=True,
|
||||
manufacturer_part_detail = enable_filter(
|
||||
ManufacturerPartSerializer(
|
||||
label=_('Manufacturer Part'),
|
||||
source='manufacturer_part',
|
||||
part_detail=False,
|
||||
read_only=True,
|
||||
allow_null=True,
|
||||
),
|
||||
False,
|
||||
prefetch_fields=['manufacturer_part'],
|
||||
)
|
||||
|
||||
MPN = serializers.CharField(
|
||||
@@ -511,15 +497,13 @@ class SupplierPartSerializer(
|
||||
Fields:
|
||||
in_stock: Current stock quantity for each SupplierPart
|
||||
"""
|
||||
queryset = queryset.prefetch_related('part', 'pricebreaks')
|
||||
|
||||
queryset = queryset.annotate(in_stock=part.filters.annotate_total_stock())
|
||||
|
||||
queryset = queryset.annotate(
|
||||
on_order=company.filters.annotate_on_order_quantity()
|
||||
)
|
||||
|
||||
queryset = SupplierPart.annotate_parameters(queryset)
|
||||
queryset = queryset.prefetch_related('supplier', 'manufacturer_part')
|
||||
|
||||
return queryset
|
||||
|
||||
|
||||
Reference in New Issue
Block a user