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

pull/10235/head
ibuler 2 years ago
parent 5921b2ee8f
commit 8b98bbddaa

@ -1,18 +1,18 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
import re from django.db.models import F
from django.db.models import F, QuerySet
from django.db.transaction import atomic from django.db.transaction import atomic
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
from accounts.models import Account from accounts.models import Account
from accounts.serializers import AccountSerializer from accounts.serializers import AccountSerializer
from common.serializers import WritableNestedModelSerializer, SecretReadableMixin, CommonModelSerializer, \ from common.const import UUID_PATTERN
MethodSerializer from common.serializers import (
from common.serializers.dynamic import create_serializer_class WritableNestedModelSerializer, SecretReadableMixin,
CommonModelSerializer, MethodSerializer
)
from common.serializers.fields import LabeledChoiceField from common.serializers.fields import LabeledChoiceField
from orgs.mixins.serializers import BulkOrgResourceModelSerializer from orgs.mixins.serializers import BulkOrgResourceModelSerializer
from ...const import Category, AllTypes from ...const import Category, AllTypes
@ -25,8 +25,6 @@ __all__ = [
'AccountSecretSerializer', 'AssetProtocolsPermsSerializer' '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): class AssetProtocolsSerializer(serializers.ModelSerializer):
port = serializers.IntegerField(required=False, allow_null=True, max_value=65535, min_value=1) 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=()) protocols = AssetProtocolsSerializer(many=True, required=False, label=_('Protocols'), default=())
accounts = AssetAccountSerializer(many=True, required=False, allow_null=True, write_only=True, label=_('Account')) 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")) nodes_display = serializers.ListField(read_only=False, required=False, label=_("Node path"))
custom_info = MethodSerializer(label=_('Custom info'))
class Meta: class Meta:
model = Asset model = Asset
fields_mini = ['id', 'name', 'address'] 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_fk = ['domain', 'platform']
fields_m2m = [ fields_m2m = [
'nodes', 'labels', 'protocols', 'nodes', 'labels', 'protocols',
@ -193,36 +190,6 @@ class AssetSerializer(BulkOrgResourceModelSerializer, WritableNestedModelSeriali
.annotate(type=F("platform__type")) .annotate(type=F("platform__type"))
return queryset 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 @staticmethod
def perform_nodes_display_create(instance, nodes_display): def perform_nodes_display_create(instance, nodes_display):
if not nodes_display: if not nodes_display:
@ -336,8 +303,8 @@ class DetailMixin(serializers.Serializer):
def get_instance(self): def get_instance(self):
request = self.context.get('request') request = self.context.get('request')
if not self.instance and uuid_pattern.findall(request.path): if not self.instance and UUID_PATTERN.findall(request.path):
pk = uuid_pattern.findall(request.path)[0] pk = UUID_PATTERN.findall(request.path)[0]
self.instance = Asset.objects.filter(id=pk).first() self.instance = Asset.objects.filter(id=pk).first()
return self.instance return self.instance

@ -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 from .common import AssetSerializer
__all__ = ['CustomSerializer'] __all__ = ['CustomSerializer']
class CustomSerializer(AssetSerializer): class CustomSerializer(AssetSerializer):
custom_info = MethodSerializer(label=_('Custom info'))
class Meta(AssetSerializer.Meta): class Meta(AssetSerializer.Meta):
model = Custom 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)()

@ -1,3 +1,5 @@
import re
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
create_success_msg = _("%(name)s was created successfully") create_success_msg = _("%(name)s was created successfully")
@ -9,3 +11,4 @@ KEY_CACHE_RESOURCE_IDS = "RESOURCE_IDS_{}"
# AD User AccountDisable # AD User AccountDisable
# https://docs.microsoft.com/en-us/troubleshoot/windows-server/identity/useraccountcontrol-manipulate-account-properties # https://docs.microsoft.com/en-us/troubleshoot/windows-server/identity/useraccountcontrol-manipulate-account-properties
LDAP_AD_ACCOUNT_DISABLE = 2 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}')

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

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

Loading…
Cancel
Save