rest_framework 中 serializers 学习记录

SerializerMethodField()

用于只读字段,通过序列化器类型的父类,会自动调用函数名为 get_{filed_name} 的函数,对返回的结果进行处理。

使用方式:

 class ExampleSerializer(self):
        extra_info = SerializerMethodField()

        def get_extra_info(self, obj):
            return ...  # Calculate some data to return.
# 实战代码来自 @大江狗,略微经过修改
class ArticleSerializers(serializers.ModelSerializer):
    author = serializers.HiddenField(default=serializers.CurrentUserDefault())
    cn_status = serializers.SerializerMethodField()

    class Meta:
        model = Article
        fields = '__all__'
        read_only_fields = ('id', 'create_date')

    def get_cn_status(self, obj):
        status_dict = {
    
    'p': '已发表', 'd': '草稿'}
        if status_dict.get(obj.status):
            return status_dict[obj.status]
        return '未知'
# 也可以编写任意名字的函数,在 SerializerMethodField 实例化时以 method_name 传入字符串形式的函数名(不推荐)
class ArticleSerializers(serializers.ModelSerializer):
    author = serializers.HiddenField(default=serializers.CurrentUserDefault())
    # 实例化时传入自定义的函数名
    cn_status = serializers.SerializerMethodField(method_name='add_cn_status')

    class Meta:
        model = Article
        fields = '__all__'
        read_only_fields = ('id', 'create_date')
	# 自定义一个函数名
    def add_cn_status(self, obj):
        status_dict = {
    
    'p': '已发表', 'd': '草稿'}
        if status_dict.get(obj.status):
            return status_dict[obj.status]
        return '未知'

在这里插入图片描述
通过 SerializerMethodField 类,我们对 status 这一参数进行了二次加工,增加了中文显示类,注意这里的 cn_status 只读,无法进行修改和增加。

代码分析

class SerializerMethodField(Field):
"""
该类是 Field 的子类
"""
    def __init__(self, method_name=None, **kwargs):
    # 初始化时接受 method_name 这一参数的值作为返回前二次处理的函数
        self.method_name = method_name
        # 设置要查找的模型字段为所有字段
        kwargs['source'] = '*'
        # 默认该字段为空字段 
        kwargs['read_only'] = True
        super().__init__(**kwargs)

    def bind(self, field_name, parent):
        # The method name defaults to `get_{field_name}`.
        # 如果初始化时没有传入对应 methhod_name,会自动将 get_{field_name} 这一形式的函数作为二次处理函数进行绑定
        if self.method_name is None:
            self.method_name = 'get_{field_name}'.format(field_name=field_name)

        super().bind(field_name, parent)

    def to_representation(self, value):
        method = getattr(self.parent, self.method_name)
        return method(value)

补充内容

在这里插入图片描述
通过查阅官方文档我们可以看到,在使用模型作为序列化对象时需要提供 source 的默认值,方便框架定位具体需要展示的字段。但在 SerializerMethodField 中不确定我们会使用到模型中的哪个字段进行二次加工,所以传入 * 表示整个模型对象都需要传入。

猜你喜欢

转载自blog.csdn.net/qq_20728575/article/details/127509687
今日推荐