import copy from rest_framework import serializers from rest_framework.serializers import Serializer from rest_framework.serializers import ModelSerializer from rest_framework_bulk.serializers import BulkListSerializer from common.mixins import BulkListSerializerMixin from django.utils.functional import cached_property from rest_framework.utils.serializer_helpers import BindingDict from common.mixins.serializers import BulkSerializerMixin __all__ = [ 'MethodSerializer', 'EmptySerializer', 'BulkModelSerializer', 'AdaptedBulkListSerializer', 'CeleryTaskSerializer' ] # MethodSerializer # ---------------- class MethodSerializer(serializers.Serializer): def __init__(self, method_name=None, **kwargs): self.method_name = method_name super().__init__(**kwargs) class Meta: # 生成swagger时使用 ref_name = None def bind(self, field_name, parent): if self.method_name is None: method_name = 'get_{field_name}_serializer'.format(field_name=field_name) self.method_name = method_name super().bind(field_name, parent) @cached_property def serializer(self) -> serializers.Serializer: method = getattr(self.parent, self.method_name) _serializer = method() # 设置serializer的parent值,否则在serializer实例中获取parent会出现断层 setattr(_serializer, 'parent', self.parent) return _serializer @cached_property def fields(self): """ 重写此方法因为在 BindingDict 中要设置每一个 field 的 parent 为 `serializer`, 这样在调用 field.parent 时, 才会达到预期的结果, 比如: serializers.SerializerMethodField """ return self.serializer.fields def run_validation(self, data=serializers.empty): return self.serializer.run_validation(data) def to_representation(self, instance): return self.serializer.to_representation(instance) def get_initial(self): return self.serializer.get_initial() # Other Serializer # ---------------- class EmptySerializer(Serializer): pass class BulkModelSerializer(BulkSerializerMixin, ModelSerializer): pass class AdaptedBulkListSerializer(BulkListSerializerMixin, BulkListSerializer): pass class CeleryTaskSerializer(serializers.Serializer): task = serializers.CharField(read_only=True)