Serializers 序列化组件——ModelSerializer详解_anmi3721的博客-程序员秘密

技术标签: ViewUI  python  前端  

  前面学习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区别

  

 

转载于:https://www.cnblogs.com/xiugeng/p/11460855.html

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/anmi3721/article/details/101666364

智能推荐

《计算机网络 第八版 》第四章(网路层)复习_法钵罩不住的柔情的博客-程序员秘密

关键词: 几个重要的概念、网际协议IP、IP的格式、ARP、ICMP、IGMP、分类IP地址、无分类编址CIDR、一、问题描述电路交换与虚电路的相同之处和不同答:虚电路表示这只是一条逻辑上的连接,分组都沿着这条逻辑连接按照存储转发方式传送,而并不是真正建立了一条物理连接。请注意,电路交换的电话通信是先建立了一条真正的连接。通常与网际层的IP协议配套使用的协议有那三个?答:地址解析协议ARP(Address Resolution Protocol)、网际控制报文协议ICMP(Interne

传智播客-递归(3)-文件目录列表的树状显示_fjf133的博客-程序员秘密

顾名思义,就是写一段代码,显示指定文件的结构图,包括其所有子目录,子目录的子目录和非目录文件。1、以缩进的形式打印出指定文件的目录结构。这个缩进是以两个空格表示的。即文件每延后一级,打印的时候就在前面多加两个空格。采用递归方法设计的思考要点(详情请参见递归(1)),具体步骤为:(1)在main方法里,a,给定文件(file=File(String pathName));b,列出目录并打印。(2

【Flutter从入门到实战】⑰Flutter的主题风格、Theme、DarkTheme暗黑模式、单独给单个页面设置Theme、屏幕适配、屏幕适配工具类封装、Flutter调试使用_flutter theme_宇夜iOS的博客-程序员秘密

【Flutter从入门到实战】⑰Flutter的主题风格、Theme、DarkTheme暗黑模式、单独给单个页面设置Theme、屏幕适配、屏幕适配工具类封装、Flutter调试使用

非线性最小二乘法矩阵处理_在制订公差标准时,必须掌握加工的极限误差 答案_Phyllis_C的博客-程序员秘密

把非线性转化为线性,再求解。在制定公差标准时,必须掌握加工的极限误差随工件尺寸变化的规律。例如,对用普通车床切削外圆进行了大量实验,得到加工极限误差t与工作直径D的统计资料如下: 将数据画成折线图: 可以很清楚的观察出数据是非线性的。假设这条曲线的方程是, 将其两边取对数,得到, 令,得到y=c+bx 。 再根据一元回归最小二乘法计算:

一步步搭建Spring+Spring MVC+Hibernate系统框架+登录与注册功能_天地炫舞的博客-程序员秘密

Spring+Spring MVC + Hibernate1新建WEB项目1.1先设置myeclipse编码格式,JSP、workspace1.2新建web工程 1.3避免MyEclipse验证js文件,先在web项目上单击右键,再选择“Myecplise------->open in explorer”,在下图.project文件中删除如右图代码2安装Hibernate和Spring2.1...

事务的commit work与rollback work_LebronRan的博客-程序员秘密

只是对这两个命令的简单介绍:一个数据库事务起始于一个SQL语句,中止于以下4种事件之一:COMMIT或ROLLBACK语句DDL/DCL隐式提交用户退出时自动提交系统强行关闭时取消事务事务结束后,下一条SQL语句将开始一个新的事务。语句 功能 COMMIT 结束当前事务,并将所有数据变更提交数据库生效 SAVEPOINT  name 在当前事务内部创

随便推点

C语言——结构体内存对齐_迷亭君的博客-程序员秘密

结构体内存对齐大家有没有想过这样的问题,结构体的成员变量在内存中如何存放?是否就是按照顺序依次排列吗?让我们简单看一下下面的代码:#include <stdio.h>struct A{ char c1; int i; char c2;};int main(){ printf("%d\n ", sizeof(struct A)); return 0;}根据直觉,感觉结果应该是1+4+1=6但是结果如下:为什么会出现这种情况呢?这就要提到今天的

Java高并发的写入mysql_高并发写入mysql的设计_weixin_39559079的博客-程序员秘密

最近开发一个项目。客户端每隔10秒提交100行数据给服务端,服务端查重后写入。客户端约在几万左右,提交数据比较集中,不考虑读数据的问题。现在的设计是:数据库按客户端进行分表。每个表的数据量不高。服务端获得数据后,先插入redis队列,然后在通过定时任务插入数据库。问题是:1、服务端提供给客户端的接口,是否能满足几千上万的客户端同时post数据(客户端是10秒提交一次)?2、将数据首先保存在redi...

【登录界面】vue、element-ui登录界面模板_vue登录页面模板_齊 天 大 聖的博客-程序员秘密

这里总结一个用vue、element-ui写的登录界面,为以后复制粘贴备用。/*布局容器样式 main header fotter*///点击登录按钮后发送ajax请求给后端进行账号密码比对。/*放账号密码input的div*//* 输入框样式*/

Winform 数据绑定_weixin_30339969的博客-程序员秘密

1.DataGridView数据绑定 1 namespace WindowsFormsApplication1 2 { 3 public partial class Form1 : Form 4 { 5 private List<Student> _students = new List<Student>()...

Kafka 中使用 Avro 序列化组件(三):Confluent Schema Registry【转载】_kafka-serde-tools-package_pf1234321的博客-程序员秘密

1. schema 注册表无论是使用传统的Avro API自定义序列化类和反序列化类还是使用Twitter的Bijection类库实现Avro的序列化与反序列化,这两种方法都有一个缺点:在每条Kafka记录里都嵌入了schema,这会让记录的大小成倍地增加。但是不管怎样,在读取记录时仍然需要用到整个 schema,所以要先找到 schema。有没有什么方法可以让数据共用一个schema?我...

数字信号处理中各种频率关系_iteye_4185的博客-程序员秘密

4种频率及其数量关系实际物理频率表示AD采集物理信号的频率,fs为采样频率,由奈奎斯特采样定理可以知道,fs必须≥信号最高频率的2倍才不会发生信号混叠,因此fs能采样到的信号最高频率为fs/2。角频率是物理频率的2*pi倍,这个也称模拟频率。归一化频率是将物理频率按fs归一化之后的结果,最高的信号频率为fs/2对应归一化频率0.5,这也就是为什么在matlab的fd...

推荐文章

热门文章

相关标签