perf: 优化资产批量更新

pull/9722/head
ibuler 2023-02-23 17:44:38 +08:00
parent d1b807bd8b
commit 1a9cd2dee2
3 changed files with 13 additions and 5 deletions

View File

@ -11,7 +11,6 @@ from accounts.serializers import AccountSerializerCreateValidateMixin
from accounts.serializers import AuthValidateMixin from accounts.serializers import AuthValidateMixin
from common.serializers import WritableNestedModelSerializer, SecretReadableMixin, CommonModelSerializer from common.serializers import WritableNestedModelSerializer, SecretReadableMixin, CommonModelSerializer
from common.serializers.fields import LabeledChoiceField from common.serializers.fields import LabeledChoiceField
from common.utils import lazyproperty
from orgs.mixins.serializers import BulkOrgResourceModelSerializer from orgs.mixins.serializers import BulkOrgResourceModelSerializer
from ...const import Category, AllTypes from ...const import Category, AllTypes
from ...models import Asset, Node, Platform, Label, Protocol from ...models import Asset, Node, Platform, Label, Protocol
@ -205,7 +204,7 @@ class AssetSerializer(BulkOrgResourceModelSerializer, WritableNestedModelSeriali
nodes_to_set.append(node) nodes_to_set.append(node)
instance.nodes.set(nodes_to_set) instance.nodes.set(nodes_to_set)
@lazyproperty @property
def _initial_data_platform(self): def _initial_data_platform(self):
if self.instance: if self.instance:
return self.instance.platform return self.instance.platform

View File

@ -29,13 +29,12 @@ class BaseUserPermedAssetsApi(SelfOrPKUserMixin, ListAPIView):
ordering_fields = ("name", "address") ordering_fields = ("name", "address")
filterset_class = AssetFilterSet filterset_class = AssetFilterSet
serializer_class = serializers.AssetPermedSerializer serializer_class = serializers.AssetPermedSerializer
only_fields = serializers.AssetPermedSerializer.Meta.only_fields
def get_queryset(self): def get_queryset(self):
if getattr(self, 'swagger_fake_view', False): if getattr(self, 'swagger_fake_view', False):
return Asset.objects.none() return Asset.objects.none()
assets = self.get_assets() assets = self.get_assets()
assets = assets.prefetch_related('platform').only(*self.only_fields) assets = self.serializer_class.setup_eager_loading(assets)
return assets return assets
@abc.abstractmethod @abc.abstractmethod

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
from django.db.models import F
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from rest_framework import serializers from rest_framework import serializers
@ -32,9 +33,18 @@ class AssetPermedSerializer(OrgResourceModelSerializerMixin):
"id", "name", "address", 'domain', 'platform', "id", "name", "address", 'domain', 'platform',
"comment", "org_id", "is_active", "comment", "org_id", "is_active",
] ]
fields = only_fields + ['protocols', 'category', 'type', 'spec_info'] + ['org_name'] fields = only_fields + ['protocols', 'category', 'type'] + ['org_name']
read_only_fields = fields read_only_fields = fields
@classmethod
def setup_eager_loading(cls, queryset):
""" Perform necessary eager loading of data. """
queryset = queryset.prefetch_related('domain', 'nodes', 'labels') \
.prefetch_related('platform', 'protocols') \
.annotate(category=F("platform__category")) \
.annotate(type=F("platform__type"))
return queryset
class NodePermedSerializer(serializers.ModelSerializer): class NodePermedSerializer(serializers.ModelSerializer):
class Meta: class Meta: