Fix for N+1 issues in stock item serializing (#12534)

This commit is contained in:
Oliver
2026-08-01 20:35:11 +10:00
committed by GitHub
parent 175bfda22f
commit d024a3fe2f
3 changed files with 23 additions and 4 deletions
+9 -1
View File
@@ -143,8 +143,16 @@ class StockItemSerialize(StockItemContextMixin, CreateAPI):
queryset = StockSerializers.StockItemSerializer.annotate_queryset(items) queryset = StockSerializers.StockItemSerializer.annotate_queryset(items)
# Apply any additional prefetching required by optional fields which end up
# included in this response (e.g. 'tags', 'tests') - mirrors what
# OutputOptionsMixin.get_queryset() does for a normal list/retrieve request,
# which this manually-constructed response bypasses
context = self.get_serializer_context()
probe_serializer = StockSerializers.StockItemSerializer(context=context)
queryset = probe_serializer.prefetch_queryset(queryset)
response = StockSerializers.StockItemSerializer( response = StockSerializers.StockItemSerializer(
queryset, many=True, context=self.get_serializer_context() queryset, many=True, context=context
) )
return Response(response.data, status=status.HTTP_201_CREATED) return Response(response.data, status=status.HTTP_201_CREATED)
+13 -1
View File
@@ -2489,7 +2489,18 @@ class StockItem(
# Create a new tracking entry for each item # Create a new tracking entry for each item
history_items = [] history_items = []
# Every new item shares this exact part - avoid a redundant per-item
# part_id -> Part lookup (bulk_create_and_fetch() does not preserve the
# cached FK) by seeding each item's cache with the instance we already have
part = self.part
# Check (once) whether there are any test results to copy across, rather
# than re-querying an identical (and usually empty) result set per item
has_test_results = self.test_results.exists()
for item in items: for item in items:
item.part = part
# Construct tracking entries for the new StockItem # Construct tracking entries for the new StockItem
if entry := item.add_tracking_entry( if entry := item.add_tracking_entry(
StockHistoryCode.SPLIT_FROM_PARENT, StockHistoryCode.SPLIT_FROM_PARENT,
@@ -2512,7 +2523,8 @@ class StockItem(
history_items.append(entry) history_items.append(entry)
# Copy any test results from this item to the new one # Copy any test results from this item to the new one
item.copyTestResultsFrom(self) if has_test_results:
item.copyTestResultsFrom(self)
StockItemTracking.objects.bulk_create(history_items, batch_size=250) StockItemTracking.objects.bulk_create(history_items, batch_size=250)
+1 -2
View File
@@ -1702,9 +1702,8 @@ class StockItemTest(StockAPITestCase):
with self.settings( with self.settings(
PLUGIN_TESTING_EVENTS=True, PLUGIN_TESTING_EVENTS_ASYNC=True PLUGIN_TESTING_EVENTS=True, PLUGIN_TESTING_EVENTS_ASYNC=True
): ):
# TODO: 2026-07-12 : Refactor this API call
response = self.post( response = self.post(
url, data, max_query_count=1300, benchmark=True, format='json' url, data, max_query_count=150, benchmark=True, format='json'
) )
self.assertEqual(response.status_code, 201) self.assertEqual(response.status_code, 201)