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) return method() def get_fields(self): return self.serializer.get_fields() @cached_property def fields(self): """ 重写此方法因为在 BindingDict 中要设置每一个 field 的 parent 为 `serializer`, 这样在调用 field.parent 时, 才会达到预期的结果, 比如: serializers.SerializerMethodField """ fields = BindingDict(self.serializer) for key, value in self.get_fields().items(): fields[key] = value return fields # 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)