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

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
    }
]

对上面这些场景使用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__"
    

    返回的结果:

    [
        {
            "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
        }
    ]
    

    注意:为什么添加了 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()
    '男'
    >>>
    
  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__"
    

    返回的结果:

    [
        {
            "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
        }
    ]
    
  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__"
    

    返回的结果:

    [
        {
            "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
        }
    ]
    

你可能感兴趣的:(django,数据库,sqlite)