• Django系列之Serializer的source参数使用、自定义序列化方法


    数据准备

    models.py

    from django.contrib.auth.models import AbstractUser
    from django.db import models
    
    
    class Publish(models.Model):
        name = models.CharField(max_length=32)
        city = models.CharField(max_length=8)
        email = models.CharField(max_length=32)
        
        def __str__(self):
            return self.name
    
    
    class AuthorDetail(models.Model):
        birthday = models.DateField()
        telephone = models.BigIntegerField()
        addr = models.CharField(max_length=64)
    
    
    class Author(models.Model):
        name = models.CharField(max_length=32)
        age = models.IntegerField()
        gender = models.IntegerField(choices=(('1', '男'), ('0', '女')))
        ad = models.OneToOneField(AuthorDetail, on_delete=models.CASCADE, null=True)
    
        def __str__(self):
            return self.name
    
    
    class Book(models.Model):
        title = models.CharField(max_length=32)
        price = models.DecimalField(max_digits=5, decimal_places=2)
        pub_date = models.DateField()
        publish = models.ForeignKey(Publish, on_delete=models.CASCADE, null=True)
        authors = models.ManyToManyField(Author, db_table="book2author")
    
        def __str__(self):
            return self.title
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    serializers字段的source参数

    使用默认的序列化器时,视图函数访问 具有choices参数 的字段或 一对一一对多多对多 字段时,返回的数据只有 id 值,就像下面这种方式,性别是0或1,居住地址是居住详情表中的id值:

    [
        {
            "id": 1,
            "name": "阿明",
            "age": 16,
            "gender": 1,
            "ad": 1
        },
        {
            "id": 3,
            "name": "阿美",
            "age": 21,
            "gender": 0,
            "ad": 3
        }
    ]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    对上面这些场景使用source参数:

    1. get_xxx_display 用于显示 choices 参数对应的文本信息。
      serializers.py

      class AuthorSerializer(serializers.ModelSerializer):
      gender_txt = serializers.CharField(source='get_gender_display')		# 使用get_xxx_display
      
      class Meta:
          model = Author
          fields = "__all__"
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6

      返回的结果:

      [
          {
              "id": 1,
              "gender_txt": "男",
              "name": "阿明",
              "age": 16,
              "gender": "1",
              "ad": 1
          },
          {
              "id": 2,
              "gender_txt": "男",
              "name": "阿伟",
              "age": 25,
              "gender": "1",
              "ad": 2
          },
          {
              "id": 3,
              "gender_txt": "男",
              "name": "阿华",
              "age": 21,
              "gender": "1",
              "ad": 3
          },
          {
              "id": 4,
              "gender_txt": "女",
              "name": "阿美",
              "age": 16,
              "gender": "0",
              "ad": 4
          }
      ]
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34

      注意:为什么添加了 source=get_xxx_display 还是没有显示出对应文本信息?把 choices=(('1', '男'), ('0', '女')) 的 0 和 1 改成字符串形式再试试。

      当然,也可以在视图函数中,使用 obj.get_xxx.display() 来获取choices文本值。

      >>> Author.objects.get(id=1).gender
      '1'
      >>> Author.objects.get(id=1).get_gender_display()
      '男'
      >>>
      
      • 1
      • 2
      • 3
      • 4
      • 5
    2. 显示 一对一一对多多对多 字段对应的文本信息。
      serializers.py

      class AuthorSerializer(serializers.ModelSerializer):
          gender_txt = serializers.CharField(source='get_gender_display')
          address_txt = serializers.CharField(source='ad.addr')	# 支持连表查询
      
          class Meta:
              model = Author
              fields = "__all__"
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7

      返回的结果:

      [
          {
              "id": 1,
              "gender_txt": "男",
              "address_txt": "beijing",
              "name": "阿明",
              "age": 16,
              "gender": "1",
              "ad": 1
          },
          {
              "id": 2,
              "gender_txt": "男",
              "address_txt": "shanghai",
              "name": "阿伟",
              "age": 25,
              "gender": "1",
              "ad": 2
          },
          {
              "id": 3,
              "gender_txt": "男",
              "address_txt": "shanghai",
              "name": "阿华",
              "age": 21,
              "gender": "1",
              "ad": 3
          },
          {
              "id": 4,
              "gender_txt": "女",
              "address_txt": "guangzhou",
              "name": "阿美",
              "age": 16,
              "gender": "0",
              "ad": 4
          }
      ]
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
    3. 自定义序列化输出方法

      class AuthorSerializer(serializers.ModelSerializer):
          gender_txt = serializers.CharField(source='get_gender_display')
          address_zidingyi = serializers.SerializerMethodField()		# 自定义序列化方法, 会寻找并执行'get_xxx'的方法。
      
          def get_address_zidingyi(self, obj):
              return obj.ad.addr
      
          class Meta:
              model = Author
              fields = "__all__"
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10

      返回的结果:

      [
          {
              "id": 1,
              "gender_txt": "男",
              "address_zidingyi": "beijing",
              "name": "阿明",
              "age": 16,
              "gender": "1",
              "ad": 1
          },
          {
              "id": 2,
              "gender_txt": "男",
              "address_zidingyi": "shanghai",
              "name": "阿伟",
              "age": 25,
              "gender": "1",
              "ad": 2
          },
          {
              "id": 3,
              "gender_txt": "男",
              "address_zidingyi": "shanghai",
              "name": "阿华",
              "age": 21,
              "gender": "1",
              "ad": 3
          },
          {
              "id": 4,
              "gender_txt": "女",
              "address_zidingyi": "guangzhou",
              "name": "阿美",
              "age": 16,
              "gender": "0",
              "ad": 4
          }
      ]
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
  • 相关阅读:
    Metasploit入门用法
    Vector 模拟实现
    RSA加密和解密原理及过程(非对称加密)
    Seata0.7.1配合nacos实现分布式事务
    OJ_最大序列和
    Linux——操作指令(ls,cd,touch,mkdir,tree,pwd,rm,man,cp)
    Java泛型接口以及案例说明(四)
    Kubernetes部署
    C++八皇后问题代码
    前端自动化测试入门教程
  • 原文地址:https://blog.csdn.net/CSDN1csdn1/article/details/134227544