• Serializers 序列化组件——ModelSerializer详解


      前面学习Serializers用法时,发现所有的序列化都与我们的模型紧密相关。

      django_restframework也给我提供了跟模型紧密相关的序列化器——ModelSerializer。

      它会根据模型自动生成一组字段;它简单的默认实现了.update()以及.create()方法。

    一、ModelSerializer序列化

    1、定义ModelSerializer序列化器

    # 针对models设计和声明序列化类
    from rest_framework import serializers
    from .models import Book, Publisher
    
    
    class BookSerializer(serializers.ModelSerializer):
        class Meta:
            model = Book         # 与Book表对应
    
            # 这三种情况不能同时使用
            # 1.取全部字段
            fields = "__all__"
    
            # 2.自定义包含字段
            # fields = ["id", "title", "pub_time"]
            # 输出:[{"id": 1, "title": "python开发", "pub_time": "2011-08-27"},...]
    
            # 3.排除某些字段
            # exclude = ["id", "category","author", "publisher"]
            # 输出:[{"title": "python开发", "pub_time": "2011-08-27"},...]

      需要注意的是:取全部字段、取自定义字段、排除某些字段这三种筛选不能同时使用。

    2、外键关系的序列化

      注意:当序列化类META定义了depth时,这个序列化类中引用字段(外键)则自动变为只读。

      depth 代表找嵌套关系的第几层。

    class BookSerializer(serializers.ModelSerializer):
        class Meta:
            model = Book         # 与Book表对应
            fields = "__all__"
            depth = 1

      添加depth前,显示效果:

      

      添加depth后,显示效果:

       

      由上图可知,只会查看嵌套深度一层的内容。

    3、自定义字段

      很多字段默认显示的是选择的key值,但要给用户展示的是value值。

      因此可以声明一些字段来覆盖默认字段来进行自定制。

    class BookSerializer(serializers.ModelSerializer):
        category = serializers.CharField(source="get_category_display")   # 找到对应中文
    
        class Meta:
            model = Book         # 与Book表对应
            fields = "__all__"

      显示效果如下所示:

      

    4、Meta中其他关键字参数

      官方文档地址:https://www.django-rest-framework.org/api-guide/serializers/

    (1)指定只读字段

      希望将多个字段指定为只读。推荐使用快捷的Meta选项read_only_fields,而不是显式地使用read_only=True属性添加每个字段。示例如下所示:

    class BookSerializer(serializers.ModelSerializer):
        chapter = serializers.CharField(source="get_chapter_display", read_only=True)
    
        class Meta:
            model = Book
            fields = "__all__"
            depth = 1
            read_only_fields = ["id"]

      模型字段有设置 editable=False, AutoField 字段默认设置为只读,不需要添加到 read_only_fields 选项。

    (2)给字段添加额外参数——extra_kwargs

      使用extra_kwargs参数为ModelSerializer添加或修改原有的选项参数---字典格式。

    # 示例一:
    class BookSerializer(serializers.ModelSerializer):
        chapter = serializers.CharField(source="get_chapter_display", read_only=True)
    
        class Meta:
            model = Book
            fields = "__all__"
            depth = 1
            read_only_fields = ["id"]
            extra_kwargs = {"title": {"validators": [my_validate,]}}
    
    
    # 示例二:
    class CreateUserSerializer(serializers.ModelSerializer):
        class Meta:
            model = User
            fields = ['email', 'username', 'password']
            extra_kwargs = {'password': {'write_only': True}}

      如果字段已在序列化程序类中显式声明,则该extra_kwargs选项将被忽略。

    5、post和patch请求

      由于depth会让外键变成只读,所以定义一个序列化的类,其实只要去掉depth就可以了。

    class BookSerializer(serializers.ModelSerializer):
        chapter = serializers.CharField(source="get_chapter_display", read_only=True)
    
        class Meta:
            model = Book
            fields = "__all__"
            # fields = ["id", "title", "pub_time"]
            # exclude = ["user"]
            # 分别是所有字段 包含某些字段 排除某些字段
            read_only_fields = ["id"]
            extra_kwargs = {"title": {"validators": [my_validate,]}}

    6、SerializerMethodField

      外键关联的对象有很多字段是用不到的,都传给前端会有数据冗余。需要自己去定制序列化外键对象的那些字段。

    # 针对models设计和声明序列化类
    from rest_framework import serializers
    from .models import Book, Publisher
    
    class BookSerializer(serializers.ModelSerializer):
        category = serializers.CharField(source="get_category_display")   # 找到对应中文
    
        class Meta:
            model = Book         # 与Book表对应
            fields = "__all__"

      查看页面 http://127.0.0.1:8000/books/list,显示效果如下所示:

      

      添加 SerializerMethodField的使用,获取显示外联字段:

    class BookSerializer(serializers.ModelSerializer):
        category = serializers.CharField(source="get_category_display")   # 找到对应中文
    
        # SerializerMethodField的使用,获取显示外联字段
        publisher = serializers.SerializerMethodField()
        author= serializers.SerializerMethodField()
    
        def get_author(self, obj):
            authors_query_set = obj.author.all()   # 拿到所有作者信息
            return [{"id": authors_obj.id, "name": authors_obj.name} for authors_obj in authors_query_set]   # 列表推导式
    
        def get_publisher(self, obj):
            # obj是我们序列化的每个Book对象
            publisher_obj = obj.publisher   # 正向查询
            return {'id': publisher_obj.id}
    
        class Meta:
            model = Book         # 与Book表对应
            fields = "__all__"

      显示效果如下所示:

      

    二、ModelSerializer反序列化

    1、ModelSerializer原生POST请求  

      再将 SerDemo/serializers.py 下 BookSerializer 恢复为原生状态:

    class BookSerializer(serializers.ModelSerializer):
        class Meta:
            model = Book         # 与Book表对应
            fields = "__all__"

      不用自定义create方法,可直接提交提交post请求如下:

      

      数据新增成功,如下所示:

      

    2、SerializerMethodField改写

    class BookSerializer(serializers.ModelSerializer):
        # SerializerMethodField的使用,获取显示外联字段
        category_display = serializers.SerializerMethodField(read_only=True)   # 重新定义,避免重写,影响反序列化
        publisher_info = serializers.SerializerMethodField(read_only=True)
        authors = serializers.SerializerMethodField(read_only=True)
    
        def get_category_display(self, obj):
            return obj.get_category_display()  # ORM方法获取中文
    
        def get_authors(self, obj):
            authors_query_set = obj.author.all()   # 拿到所有作者信息
            return [{"id": authors_obj.id, "name": authors_obj.name} for authors_obj in authors_query_set]   # 列表推导式
    
        def get_publisher_info(self, obj):
            # obj是我们序列化的每个Book对象
            publisher_obj = obj.publisher   # 正向查询
            return {'id': publisher_obj.id}
    
        class Meta:
            model = Book         # 与Book表对应
            fields = "__all__"

      显示效果如下所示:

      

      可以从上图看到,除了显示了category_display、authors、publisher_info,也显示了category、publisher、author。

    3、extra_kwargs配置字段参数

    class BookSerializer(serializers.ModelSerializer):
        # SerializerMethodField的使用,获取显示外联字段
        category_display = serializers.SerializerMethodField(read_only=True)   # 重新定义,避免重写,影响反序列化
        publisher_info = serializers.SerializerMethodField(read_only=True)
        authors = serializers.SerializerMethodField(read_only=True)
    
        def get_category_display(self, obj):
            return obj.get_category_display()  # ORM方法获取中文
    
        def get_authors(self, obj):
            authors_query_set = obj.author.all()   # 拿到所有作者信息
            return [{"id": authors_obj.id, "name": authors_obj.name} for authors_obj in authors_query_set]   # 列表推导式
    
        def get_publisher_info(self, obj):
            # obj是我们序列化的每个Book对象
            publisher_obj = obj.publisher   # 正向查询
            return {'id': publisher_obj.id}
    
        class Meta:
            model = Book         # 与Book表对应
            fields = "__all__"
            extra_kwargs = {
                "category": {"write_only": True},   # 避免直接改写
                "publisher": {"write_only": True},
                "author": {"write_only": True}
            }

      如此就不再显示category、publisher、author了,显示效果如下所示:

      

    三、Serializer与ModelSerializer区别

      

  • 相关阅读:
    python高级(2)—— 基础回顾2
    Java System Reports
    EWA不能及时通过邮件接收
    LA服务可用性4个9是什么意思?怎么达到?
    安装HANA Rules Framework(HRF)
    RFC destination fails with error Incomplete Logon Data after system copy
    为满足中国税改,SAP该如何打SPS
    HANA数据库无法停止
    SR开启时LOG_MODE必须是normal
    2743711
  • 原文地址:https://www.cnblogs.com/xiugeng/p/11460855.html
Copyright © 2020-2023  润新知