2021-01-01 23:25:23 +00:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
#
|
2022-08-09 08:53:43 +00:00
|
|
|
import six
|
2020-07-20 02:42:22 +00:00
|
|
|
|
2022-08-09 08:53:43 +00:00
|
|
|
from rest_framework.fields import ChoiceField
|
2021-01-01 23:25:23 +00:00
|
|
|
from rest_framework import serializers
|
2022-09-06 05:27:47 +00:00
|
|
|
from django.utils.translation import gettext_lazy as _
|
2022-09-01 06:46:31 +00:00
|
|
|
from django.core.exceptions import ObjectDoesNotExist
|
2020-07-20 02:42:22 +00:00
|
|
|
|
2022-05-10 09:28:10 +00:00
|
|
|
from common.utils import decrypt_password
|
2020-07-20 02:42:22 +00:00
|
|
|
|
2021-01-01 23:25:23 +00:00
|
|
|
__all__ = [
|
2022-09-01 06:46:31 +00:00
|
|
|
'ReadableHiddenField', 'EncryptedField', 'LabeledChoiceField',
|
2022-09-01 13:00:04 +00:00
|
|
|
'ObjectRelatedField',
|
2021-01-01 23:25:23 +00:00
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
# ReadableHiddenField
|
|
|
|
# -------------------
|
|
|
|
|
|
|
|
|
|
|
|
class ReadableHiddenField(serializers.HiddenField):
|
|
|
|
""" 可读的 HiddenField """
|
|
|
|
def __init__(self, **kwargs):
|
|
|
|
super().__init__(**kwargs)
|
|
|
|
self.write_only = False
|
|
|
|
|
|
|
|
def to_representation(self, value):
|
|
|
|
if hasattr(value, 'id'):
|
|
|
|
return getattr(value, 'id')
|
|
|
|
return value
|
2022-05-07 08:20:12 +00:00
|
|
|
|
|
|
|
|
|
|
|
class EncryptedField(serializers.CharField):
|
2022-05-17 11:34:15 +00:00
|
|
|
def __init__(self, write_only=None, **kwargs):
|
|
|
|
if write_only is None:
|
|
|
|
write_only = True
|
|
|
|
kwargs['write_only'] = write_only
|
2022-05-13 09:10:29 +00:00
|
|
|
super().__init__(**kwargs)
|
|
|
|
|
2022-05-07 08:20:12 +00:00
|
|
|
def to_internal_value(self, value):
|
|
|
|
value = super().to_internal_value(value)
|
2022-05-10 09:28:10 +00:00
|
|
|
return decrypt_password(value)
|
2022-08-09 08:53:43 +00:00
|
|
|
|
|
|
|
|
2022-09-01 06:46:31 +00:00
|
|
|
class LabeledChoiceField(ChoiceField):
|
2022-08-09 08:53:43 +00:00
|
|
|
def __init__(self, *args, **kwargs):
|
2022-09-01 06:46:31 +00:00
|
|
|
super(LabeledChoiceField, self).__init__(*args, **kwargs)
|
2022-08-09 08:53:43 +00:00
|
|
|
self.choice_mapper = {
|
|
|
|
six.text_type(key): value for key, value in self.choices.items()
|
|
|
|
}
|
|
|
|
|
|
|
|
def to_representation(self, value):
|
2022-11-02 11:07:07 +00:00
|
|
|
if value is None:
|
2022-08-09 08:53:43 +00:00
|
|
|
return value
|
|
|
|
return {
|
2022-08-18 09:58:59 +00:00
|
|
|
'value': value,
|
2022-08-09 08:53:43 +00:00
|
|
|
'label': self.choice_mapper.get(six.text_type(value), value),
|
|
|
|
}
|
2022-08-31 02:06:16 +00:00
|
|
|
|
|
|
|
def to_internal_value(self, data):
|
|
|
|
if isinstance(data, dict):
|
|
|
|
return data.get('value')
|
2022-09-01 06:46:31 +00:00
|
|
|
return super(LabeledChoiceField, self).to_internal_value(data)
|
|
|
|
|
|
|
|
|
2022-09-01 13:00:04 +00:00
|
|
|
class ObjectRelatedField(serializers.RelatedField):
|
2022-09-06 05:27:47 +00:00
|
|
|
default_error_messages = {
|
|
|
|
'required': _('This field is required.'),
|
|
|
|
'does_not_exist': _('Invalid pk "{pk_value}" - object does not exist.'),
|
|
|
|
'incorrect_type': _('Incorrect type. Expected pk value, received {data_type}.'),
|
|
|
|
}
|
|
|
|
|
2022-09-01 06:46:31 +00:00
|
|
|
def __init__(self, **kwargs):
|
|
|
|
self.attrs = kwargs.pop('attrs', None) or ('id', 'name')
|
2022-09-01 13:00:04 +00:00
|
|
|
self.many = kwargs.get('many', False)
|
2022-09-01 06:46:31 +00:00
|
|
|
super().__init__(**kwargs)
|
|
|
|
|
|
|
|
def to_representation(self, value):
|
|
|
|
data = {}
|
|
|
|
for attr in self.attrs:
|
|
|
|
data[attr] = getattr(value, attr)
|
|
|
|
return data
|
|
|
|
|
|
|
|
def to_internal_value(self, data):
|
2022-09-06 05:27:47 +00:00
|
|
|
if not isinstance(data, dict):
|
2022-09-01 06:46:31 +00:00
|
|
|
pk = data
|
2022-09-06 05:27:47 +00:00
|
|
|
else:
|
|
|
|
pk = data.get('id') or data.get('pk') or data.get(self.attrs[0])
|
2022-09-01 06:46:31 +00:00
|
|
|
queryset = self.get_queryset()
|
|
|
|
try:
|
|
|
|
if isinstance(data, bool):
|
|
|
|
raise TypeError
|
|
|
|
return queryset.get(pk=pk)
|
|
|
|
except ObjectDoesNotExist:
|
|
|
|
self.fail('does_not_exist', pk_value=pk)
|
|
|
|
except (TypeError, ValueError):
|
|
|
|
self.fail('incorrect_type', data_type=type(pk).__name__)
|