diff --git a/InvenTree/part/api.py b/InvenTree/part/api.py
index 8c7258c4ee..7506bc09f4 100644
--- a/InvenTree/part/api.py
+++ b/InvenTree/part/api.py
@@ -536,15 +536,75 @@ class PartList(generics.ListCreateAPIView):
 
         kwargs['starred_parts'] = self.starred_parts
 
-        try:
-            params = self.request.query_params
-
-            kwargs['category_detail'] = str2bool(params.get('category_detail', False))
-        except AttributeError:
-            pass
-
         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)
+        else:
+            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 categories we need to query
+            category_ids = set()
+
+            for part in data:
+                cat_id = part['category']
+
+                if cat_id is not None:
+                    category_ids.add(cat_id)
+
+            # 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[cat_id]
+                else:
+                    detail = None
+
+                part['category_detail'] = detail
+
+        """
+        Determine the response type based on the request.
+        a) For HTTP requests (e.g. via the browseable API) return a DRF response
+        b) For AJAX requests, simply return a JSON rendered response.
+        """
+        if page is not None:
+            return self.get_paginated_response(data)
+        elif request.is_ajax():
+            return JsonResponse(data, safe=False)
+        else:
+            return Response(data)
+
     def perform_create(self, serializer):
         """
         We wish to save the user who created this part!
diff --git a/InvenTree/part/models.py b/InvenTree/part/models.py
index 95a8e407b9..fa19f8b075 100644
--- a/InvenTree/part/models.py
+++ b/InvenTree/part/models.py
@@ -296,8 +296,9 @@ class PartManager(models.Manager):
 
         return super().get_queryset().prefetch_related(
             'category',
+            'category__parent',
             'stock_items',
-            'builds',    
+            'builds',
         )