Browse Source

perf: custom fields 仅custom 类型资产支持

pull/10235/head
ibuler 2 years ago
parent
commit
8b98bbddaa
  1. 51
      apps/assets/serializers/asset/common.py
  2. 41
      apps/assets/serializers/asset/custom.py
  3. 3
      apps/common/const/common.py
  4. 8
      apps/common/serializers/common.py
  5. 2
      apps/common/serializers/fields.py

51
apps/assets/serializers/asset/common.py

@ -1,18 +1,18 @@
# -*- coding: utf-8 -*-
#
import re
from django.db.models import F, QuerySet
from django.db.models import F
from django.db.transaction import atomic
from django.utils.translation import ugettext_lazy as _
from rest_framework import serializers
from accounts.models import Account
from accounts.serializers import AccountSerializer
from common.serializers import WritableNestedModelSerializer, SecretReadableMixin, CommonModelSerializer, \
MethodSerializer
from common.serializers.dynamic import create_serializer_class
from common.const import UUID_PATTERN
from common.serializers import (
WritableNestedModelSerializer, SecretReadableMixin,
CommonModelSerializer, MethodSerializer
)
from common.serializers.fields import LabeledChoiceField
from orgs.mixins.serializers import BulkOrgResourceModelSerializer
from ...const import Category, AllTypes
@ -25,8 +25,6 @@ __all__ = [
'AccountSecretSerializer', 'AssetProtocolsPermsSerializer'
]
uuid_pattern = re.compile(r'[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}')
class AssetProtocolsSerializer(serializers.ModelSerializer):
port = serializers.IntegerField(required=False, allow_null=True, max_value=65535, min_value=1)
@ -121,12 +119,11 @@ class AssetSerializer(BulkOrgResourceModelSerializer, WritableNestedModelSeriali
protocols = AssetProtocolsSerializer(many=True, required=False, label=_('Protocols'), default=())
accounts = AssetAccountSerializer(many=True, required=False, allow_null=True, write_only=True, label=_('Account'))
nodes_display = serializers.ListField(read_only=False, required=False, label=_("Node path"))
custom_info = MethodSerializer(label=_('Custom info'))
class Meta:
model = Asset
fields_mini = ['id', 'name', 'address']
fields_small = fields_mini + ['custom_info', 'is_active', 'comment']
fields_small = fields_mini + ['is_active', 'comment']
fields_fk = ['domain', 'platform']
fields_m2m = [
'nodes', 'labels', 'protocols',
@ -193,36 +190,6 @@ class AssetSerializer(BulkOrgResourceModelSerializer, WritableNestedModelSeriali
.annotate(type=F("platform__type"))
return queryset
def get_custom_info_serializer(self):
request = self.context.get('request')
default_field = serializers.DictField(required=False, label=_('Custom info'))
if not request:
return default_field
if self.instance and isinstance(self.instance, (QuerySet, list)):
return default_field
if not self.instance and uuid_pattern.findall(request.path):
pk = uuid_pattern.findall(request.path)[0]
self.instance = Asset.objects.filter(id=pk).first()
platform = None
if self.instance:
platform = self.instance.platform
elif request.query_params.get('platform'):
platform_id = request.query_params.get('platform')
platform_id = int(platform_id) if platform_id.isdigit() else 0
platform = Platform.objects.filter(id=platform_id).first()
if not platform:
return default_field
custom_fields = platform.custom_fields
if not custom_fields:
return default_field
name = platform.name.title() + 'CustomSerializer'
return create_serializer_class(name, custom_fields)()
@staticmethod
def perform_nodes_display_create(instance, nodes_display):
if not nodes_display:
@ -336,8 +303,8 @@ class DetailMixin(serializers.Serializer):
def get_instance(self):
request = self.context.get('request')
if not self.instance and uuid_pattern.findall(request.path):
pk = uuid_pattern.findall(request.path)[0]
if not self.instance and UUID_PATTERN.findall(request.path):
pk = UUID_PATTERN.findall(request.path)[0]
self.instance = Asset.objects.filter(id=pk).first()
return self.instance

41
apps/assets/serializers/asset/custom.py

@ -1,9 +1,48 @@
from assets.models import Custom
from django.db.models import QuerySet
from django.utils.translation import gettext_lazy as _
from rest_framework import serializers
from assets.models import Custom, Platform, Asset
from common.const import UUID_PATTERN
from common.serializers import MethodSerializer, create_serializer_class
from .common import AssetSerializer
__all__ = ['CustomSerializer']
class CustomSerializer(AssetSerializer):
custom_info = MethodSerializer(label=_('Custom info'))
class Meta(AssetSerializer.Meta):
model = Custom
fields = AssetSerializer.Meta.fields + ['custom_info']
def get_custom_info_serializer(self):
request = self.context.get('request')
default_field = serializers.DictField(required=False, label=_('Custom info'))
if not request:
return default_field
if self.instance and isinstance(self.instance, (QuerySet, list)):
return default_field
if not self.instance and UUID_PATTERN.findall(request.path):
pk = UUID_PATTERN.findall(request.path)[0]
self.instance = Asset.objects.filter(id=pk).first()
platform = None
if self.instance:
platform = self.instance.platform
elif request.query_params.get('platform'):
platform_id = request.query_params.get('platform')
platform_id = int(platform_id) if platform_id.isdigit() else 0
platform = Platform.objects.filter(id=platform_id).first()
if not platform:
return default_field
custom_fields = platform.custom_fields
if not custom_fields:
return default_field
name = platform.name.title() + 'CustomSerializer'
return create_serializer_class(name, custom_fields)()

3
apps/common/const/common.py

@ -1,3 +1,5 @@
import re
from django.utils.translation import ugettext_lazy as _
create_success_msg = _("%(name)s was created successfully")
@ -9,3 +11,4 @@ KEY_CACHE_RESOURCE_IDS = "RESOURCE_IDS_{}"
# AD User AccountDisable
# https://docs.microsoft.com/en-us/troubleshoot/windows-server/identity/useraccountcontrol-manipulate-account-properties
LDAP_AD_ACCOUNT_DISABLE = 2
UUID_PATTERN = re.compile(r'[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}')

8
apps/common/serializers/common.py

@ -1,3 +1,5 @@
import logging
from django.utils.functional import cached_property
from django.utils.translation import gettext_lazy as _
from drf_writable_nested.serializers import WritableNestedModelSerializer as NestedModelSerializer
@ -35,7 +37,11 @@ class MethodSerializer(serializers.Serializer):
@cached_property
def serializer(self) -> serializers.Serializer:
method = getattr(self.parent, self.method_name)
_serializer = method()
try:
_serializer = method()
except Exception as e:
logging.error(e, exc_info=True)
raise e
# 设置serializer的parent值,否则在serializer实例中获取parent会出现断层
setattr(_serializer, 'parent', self.parent)
return _serializer

2
apps/common/serializers/fields.py

@ -63,7 +63,7 @@ class LabeledChoiceField(ChoiceField):
def to_representation(self, key):
if key is None:
return key
label = self.choice_mapper.get(key)
label = self.choice_mapper.get(key, key)
return {"value": key, "label": label}
def to_internal_value(self, data):

Loading…
Cancel
Save