diff --git a/apps/common/serializers/fields.py b/apps/common/serializers/fields.py index 84d4d5927..514a96fd0 100644 --- a/apps/common/serializers/fields.py +++ b/apps/common/serializers/fields.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- # +import phonenumbers from django.core.exceptions import ObjectDoesNotExist from django.utils.translation import gettext_lazy as _ from rest_framework import serializers @@ -17,6 +18,7 @@ __all__ = [ "BitChoicesField", "TreeChoicesField", "LabeledMultipleChoiceField", + "PhoneField", ] @@ -201,3 +203,11 @@ class BitChoicesField(TreeChoicesField): value = self.to_internal_value(data) self.run_validators(value) return value + + +class PhoneField(serializers.CharField): + def to_representation(self, value): + if value: + phone = phonenumbers.parse(value, 'CN') + value = {'code': '+%s' % phone.country_code, 'phone': phone.national_number} + return value diff --git a/apps/users/serializers/user.py b/apps/users/serializers/user.py index 5d239820c..e21aab06b 100644 --- a/apps/users/serializers/user.py +++ b/apps/users/serializers/user.py @@ -8,7 +8,9 @@ from django.utils.translation import ugettext_lazy as _ from rest_framework import serializers from common.serializers import CommonBulkSerializerMixin -from common.serializers.fields import EncryptedField, ObjectRelatedField, LabeledChoiceField +from common.serializers.fields import ( + EncryptedField, ObjectRelatedField, LabeledChoiceField, PhoneField +) from common.utils import pretty_string, get_logger from common.validators import PhoneValidator from rbac.builtin import BuiltinRole @@ -103,6 +105,9 @@ class UserSerializer(RolesSerializerMixin, CommonBulkSerializerMixin, serializer label=_("Password"), required=False, allow_blank=True, allow_null=True, max_length=1024, ) + phone = PhoneField( + validators=[PhoneValidator()], required=False, allow_null=True, label=_("Phone") + ) custom_m2m_fields = { "system_roles": [BuiltinRole.system_user], "org_roles": [BuiltinRole.org_user], @@ -169,7 +174,6 @@ class UserSerializer(RolesSerializerMixin, CommonBulkSerializerMixin, serializer "created_by": {"read_only": True, "allow_blank": True}, "role": {"default": "User"}, "is_otp_secret_key_bound": {"label": _("Is OTP bound")}, - "phone": {"validators": [PhoneValidator()]}, 'mfa_level': {'label': _("MFA level")}, } @@ -224,14 +228,6 @@ class UserSerializer(RolesSerializerMixin, CommonBulkSerializerMixin, serializer attrs.pop("password_strategy", None) return attrs - def to_representation(self, instance): - data = super().to_representation(instance) - phone = phonenumbers.parse(data['phone'], 'CN') - data['phone'] = { - 'code': '+%s' % phone.country_code, 'phone': phone.national_number - } - return data - def save_and_set_custom_m2m_fields(self, validated_data, save_handler, created): m2m_values = {} for f, default_roles in self.custom_m2m_fields.items():