From f548b4bd2b07ed04533356a312b8ace14ef84e8b Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Tue, 2 Mar 2021 19:18:25 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20serializer=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E9=BB=98=E8=AE=A4=E5=80=BC=EF=BC=8C=E5=89=8D=E7=AB=AF=E5=8F=AF?= =?UTF-8?q?=E4=BB=A5=E8=B0=83=E7=94=A8=20(#5666)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit perf: 优化默认值 Co-authored-by: ibuler --- apps/common/drf/metadata.py | 10 ++++---- apps/common/mixins/serializers.py | 40 +++++++++++++++++++++++++++++-- apps/users/serializers/user.py | 11 +++++---- 3 files changed, 51 insertions(+), 10 deletions(-) diff --git a/apps/common/drf/metadata.py b/apps/common/drf/metadata.py index 7d2332006..04c365d97 100644 --- a/apps/common/drf/metadata.py +++ b/apps/common/drf/metadata.py @@ -3,6 +3,7 @@ from __future__ import unicode_literals from collections import OrderedDict +import datetime from django.core.exceptions import PermissionDenied from django.http import Http404 @@ -21,7 +22,7 @@ class SimpleMetadataWithFilters(SimpleMetadata): attrs = [ 'read_only', 'label', 'help_text', 'min_length', 'max_length', - 'min_value', 'max_value', "write_only" + 'min_value', 'max_value', "write_only", ] def determine_actions(self, request, view): @@ -59,9 +60,10 @@ class SimpleMetadataWithFilters(SimpleMetadata): field_info['type'] = self.label_lookup[field] field_info['required'] = getattr(field, 'required', False) - default = getattr(field, 'default', False) - if default and isinstance(default, (str, int)): - field_info['default'] = default + default = getattr(field, 'default', None) + if default is not None and default != empty: + if isinstance(default, (str, int, bool, datetime.datetime, list)): + field_info['default'] = default for attr in self.attrs: value = getattr(field, attr, None) diff --git a/apps/common/mixins/serializers.py b/apps/common/mixins/serializers.py index ecdd31b1d..3c310c9e9 100644 --- a/apps/common/mixins/serializers.py +++ b/apps/common/mixins/serializers.py @@ -2,7 +2,7 @@ # from collections import Iterable -from django.db.models import Prefetch, F +from django.db.models import Prefetch, F, NOT_PROVIDED from django.core.exceptions import ObjectDoesNotExist from rest_framework.utils import html from rest_framework.settings import api_settings @@ -228,7 +228,43 @@ class SizedModelFieldsMixin(BaseDynamicFieldsPlugin): return fields_to_drop +class DefaultValueFieldsMixin: + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.set_fields_default_value() + + def set_fields_default_value(self): + if not hasattr(self, 'Meta'): + return + if not hasattr(self.Meta, 'model'): + return + model = self.Meta.model + for name, serializer_field in self.fields.items(): + if serializer_field.default != empty or serializer_field.required: + continue + model_field = getattr(model, name, None) + if model_field is None: + continue + if not hasattr(model_field, 'field') \ + or not hasattr(model_field.field, 'default') \ + or model_field.field.default == NOT_PROVIDED: + continue + if name == 'id': + continue + default = model_field.field.default + + if callable(default): + default = default() + if default == '': + continue + # print(f"Set default value: {name}: {default}") + serializer_field.default = default + + class DynamicFieldsMixin: + """ + 可以控制显示不同的字段,mini 最少,small 不包含关系 + """ dynamic_fields_plugins = [QueryFieldsMixin, SizedModelFieldsMixin] def __init__(self, *args, **kwargs): @@ -256,7 +292,7 @@ class EagerLoadQuerySetFields: return queryset -class CommonSerializerMixin(DynamicFieldsMixin): +class CommonSerializerMixin(DynamicFieldsMixin, DefaultValueFieldsMixin): pass diff --git a/apps/users/serializers/user.py b/apps/users/serializers/user.py index 9eb10bc5a..239b80af1 100644 --- a/apps/users/serializers/user.py +++ b/apps/users/serializers/user.py @@ -24,15 +24,17 @@ class UserSerializer(CommonBulkSerializerMixin, serializers.ModelSerializer): (1, CUSTOM_PASSWORD) ) password_strategy = serializers.ChoiceField( - choices=PASSWORD_STRATEGY_CHOICES, required=False, initial=0, - label=_('Password strategy'), write_only=True + choices=PASSWORD_STRATEGY_CHOICES, required=False, + label=_('Password strategy'), write_only=True, default=0 ) mfa_level_display = serializers.ReadOnlyField(source='get_mfa_level_display', label=_('MFA level for display')) login_blocked = serializers.SerializerMethodField(label=_('Login blocked')) can_update = serializers.SerializerMethodField(label=_('Can update')) can_delete = serializers.SerializerMethodField(label=_('Can delete')) - org_roles = serializers.ListField(label=_('Organization role name'), allow_null=True, required=False, - child=serializers.ChoiceField(choices=ORG_ROLE.choices)) + org_roles = serializers.ListField( + label=_('Organization role name'), allow_null=True, required=False, + child=serializers.ChoiceField(choices=ORG_ROLE.choices), default=["User"] + ) key_prefix_block = "_LOGIN_BLOCK_{}" class Meta: @@ -72,6 +74,7 @@ class UserSerializer(CommonBulkSerializerMixin, serializers.ModelSerializer): 'total_role_display': {'label': _('Total role name')}, 'mfa_enabled': {'label': _('MFA enabled')}, 'mfa_force_enabled': {'label': _('MFA force enabled')}, + 'role': {'default': "User"}, } def __init__(self, *args, **kwargs):