serializers序列化器-Model:高级应用

一:source和时间

前置:开始前创建表technicalUser,并添加数据到数据表中

# 技术人员表
class technicalUser(models.Model):
    db_table = "technicalUser"
    name = models.CharField(verbose_name="姓名", max_length=32)
    age = models.IntegerField(verbose_name="年龄")
    gender = models.SmallIntegerField(verbose_name="性别", choices=((1, ""), (2, "")))
    depart = models.ForeignKey(verbose_name="部门", to="Depart", on_delete=models.CASCADE)
    ctime = models.DateTimeField(verbose_name="时间", auto_now_add=True)

# 添加表后,配置url
# path('api/<str:version>/user/', views.UserView.as_view())
# 配置完成后,视图添加新视图类

class UserView(MyAPIView):

    def get(self, request, *args, **kwargs):
        queryset = technicalUser.objects.all()
        ser = TechnicalUserSerializer(instance=queryset, many=True)
        return Response(ser.data)

数据库数据

 

1、在 https://www.cnblogs.com/guanyf/p/18584479中,使用serializers.Serializer创建视图类时,必须手动添加字段,DRF为方便创建模型类,提供了ModelSerializer类

class DepartSerializer(serializers.ModelSerializer):
    class Meta:
        model = Depart
        fields = "__all__"
# 内部类必须使用Meta,model和fields为死格式,不能改变,这是DRF限制
# 接口返回
[
    {
        "id": 1,
        "name": "张三",
        "age": 18,
        "gender": 1,
        "ctime": "2024-12-04T17:37:40+08:00",
        "depart": 1
    },
    {
        "id": 2,
        "name": "李四",
        "age": 19,
        "gender": 2,
        "ctime": "2024-12-04T17:38:26+08:00",
        "depart": 2
    }
]

 2、当需要指定返回字段时,可以使用fields进行指定

class TechnicalUserSerializer(serializers.ModelSerializer):
    class Meta:
        model = technicalUser
        fields = ["name", "age", "gender"]
# 指定后,访问接口时,将显示指定的字段
# 接口返回
[
    {
        "name": "张三",
        "age": 18,
        "gender": 1
    },
    {
        "name": "李四",
        "age": 19,
        "gender": 2
    }
]

3、访问接口时,gender字段显示为1或者2,可以通过source="get_gender_display"显示配置的性别

class TechnicalUserSerializer(serializers.ModelSerializer):
    gender = serializers.CharField(source="get_gender_display")

    class Meta:
        model = technicalUser
        fields = ["name", "age", "gender"]
# 接口返回
[
    {
        "name": "张三",
        "age": 18,
        "gender": ""
    },
    {
        "name": "李四",
        "age": 19,
        "gender": ""
    }
]

3、通过ForeignKey获取相关联的数据

class TechnicalUserSerializer(serializers.ModelSerializer):
    gender = serializers.CharField(source="get_gender_display")
    # 当有多个数据时,可连续调用 如 source="depart.title.xx.xx.xx
    depart = serializers.CharField(source="depart.title") 


    class Meta:
        model = technicalUser
        fields = ["name", "age", "gender", "depart"]
# 接口返回
[
    {
        "name": "张三",
        "age": 18,
        "gender": "",
        "depart": "技术部"
    },
    {
        "name": "李四",
        "age": 19,
        "gender": "",
        "depart": "工程部"
    }
]

4、返回citme时间字段,可以通过format进行指定返回格式

class TechnicalUserSerializer(serializers.ModelSerializer):
    gender = serializers.CharField(source="get_gender_display")
    depart = serializers.CharField(source="depart.title")
    ctime = serializers.DateTimeField(format="%Y-%m-%d")

    class Meta:
        model = technicalUser
        fields = ["name", "age", "gender", "depart", "ctime"]

# 接口返回
[
    {
        "name": "张三",
        "age": 18,
        "gender": "",
        "depart": "技术部",
        "ctime": "2024-12-04"
    },
    {
        "name": "李四",
        "age": 19,
        "gender": "",
        "depart": "工程部",
        "ctime": "2024-12-04"
    }
]

二,自定义方法

 如果想要返回自定义的值,可以通过SerializerMethodField进行定义

class TechnicalUserSerializer(serializers.ModelSerializer):
    gender = serializers.CharField(source="get_gender_display")
    depart = serializers.CharField(source="depart.title")
    ctime = serializers.DateTimeField(format="%Y-%m-%d")
    # 自定义字段
    xxx = serializers.SerializerMethodField()

    class Meta:
        model = technicalUser
        fields = ["name", "age", "gender", "depart", "ctime", "xxx"]

定义了xxx时,自动触发get_xxx方法

class TechnicalUserSerializer(serializers.ModelSerializer):
    gender = serializers.CharField(source="get_gender_display")
    depart = serializers.CharField(source="depart.title")
    ctime = serializers.DateTimeField(format="%Y-%m-%d")
    # 自定义字段
    xxx = serializers.SerializerMethodField()
    
    # 自定义字段方法
   # 运行原理:当序列化时,循环获取queryset或数据对象的相关字段,当运行到xxx时,在数据库中没有找到相关字段,自动触发get_xxx方法,执行get_xxx方法时,将当前对象作为参数传递给get_xxx,也就是 obj
    def get_xxx(self, obj):
        return 'xxx'

    class Meta:
        model = technicalUser
        fields = ["name", "age", "gender", "depart", "ctime", "xxx"]

# 接口返回
[
    {
        "name": "张三",
        "age": 18,
        "gender": "",
        "depart": "技术部",
        "ctime": "2024-12-04",
        "xxx": "xxx"
    },
    {
        "name": "李四",
        "age": 19,
        "gender": "",
        "depart": "工程部",
        "ctime": "2024-12-04",
        "xxx": "xxx"
    }
]
# 通过<运行原理>我们知道obj是当前对象,那么通过obj可以调用当前对象的每个字段,修改get_xxx方法
# 自定义字段方法
def get_xxx(self, obj):
    # obj.name 获取每个对象的name值
    return "{}-{}-{}".format(obj.name, obj.age, obj.ctime)

# 接口返回
[
    {
        "name": "张三",
        "age": 18,
        "gender": "",
        "depart": "技术部",
        "ctime": "2024-12-04",
        "xxx": "张三-18-2024-12-04 09:37:40+00:00"
    },
    {
        "name": "李四",
        "age": 19,
        "gender": "",
        "depart": "工程部",
        "ctime": "2024-12-04",
        "xxx": "李四-19-2024-12-04 09:38:26+00:00"
    }
]

 三,嵌套

前置:新建表tag,并添加数据

class Tag(models.Model):
    db_table = "tag"
    caption = models.CharField(verbose_name="标签", max_length=32)

修改技术人员表添加ManyToMany字段

# 技术人员表
class technicalUser(models.Model):
    db_table = "technicalUser"
    name = models.CharField(verbose_name="姓名", max_length=32)
    age = models.IntegerField(verbose_name="年龄")
    gender = models.SmallIntegerField(verbose_name="性别", choices=((1, ""), (2, "")))
    depart = models.ForeignKey(verbose_name="部门", to="Depart", on_delete=models.CASCADE)
    ctime = models.DateTimeField(verbose_name="时间", auto_now_add=True)
    # 添加ManyToMany字段
    tags = models.ManyToManyField(verbose_name="标签", to="Tag")

问题:怎么获取人员的标签信息?

方式1:通过自定义方法获取用户的全部标签

    # 自定义字段方法
    def get_xxx(self, obj):
        queryset = obj.tags.all()
        tag_list = [{"id": tag.id, "caption": tag.caption} for tag in queryset]
        return tag_list

# 接口返回
[
    {
        "name": "张三",
        "age": 18,
        "gender": "",
        "depart": "技术部",
        "ctime": "2024-12-04",
        "xxx": [
            {
                "id": 1,
                "caption": "java程序员"
            },
            {
                "id": 2,
                "caption": "go程序员"
            }
        ]
    },
    {
        "name": "李四",
        "age": 19,
        "gender": "",
        "depart": "工程部",
        "ctime": "2024-12-04",
        "xxx": [
            {
                "id": 2,
                "caption": "go程序员"
            }
        ]
    }
]

方式二:通过嵌套的方式<针对fk<ForeignKey>和m2m<:ManyToManyField>>

1、添加tag的序列化类

class TagSerializer(serializers.ModelSerializer):
    class Meta:
        model = Tag
        fields = "__all__"

2、如果没有Depart的序列化类,添加序列化器类

class DepartSerializer(serializers.ModelSerializer):
    class Meta:
        model = Depart
        fields = "__all__"

3、修改TechnicalUserSerializer类

class TechnicalUserSerializer(serializers.ModelSerializer):
    gender = serializers.CharField(source="get_gender_display")
    # depart = serializers.CharField(source="depart.title")
    depart = DepartSerializer()  # 引用DepartSerializer
    # 引用TagSerializer
    # 注意当tags包含一个或多个对象时,加上many=True,否则报错AttributeError, 命名时,必须与数据库保持一致,如 tags = TagSerializer ,必须叫tags
tags = TagSerializer(many=True) ctime = serializers.DateTimeField(format="%Y-%m-%d") # 自定义字段 # xxx = serializers.SerializerMethodField() # 自定义字段方法 # def get_xxx(self, obj): # queryset = obj.tags.all() # tag_list = [{"id": tag.id, "caption": tag.caption} for tag in queryset] # return tag_list class Meta: model = technicalUser fields = ["name", "age", "gender", "depart", "ctime", "tags"] # 返回接口,返回数据与方式一返回的数据一致 [ { "name": "张三", "age": 18, "gender": "", "depart": { "id": 1, "title": "技术部", "order": 1, "count": 10 }, "ctime": "2024-12-04", "tags": [ { "id": 1, "caption": "java程序员" }, { "id": 2, "caption": "go程序员" } ] }, { "name": "李四", "age": 19, "gender": "", "depart": { "id": 2, "title": "工程部", "order": 2, "count": 20 }, "ctime": "2024-12-04", "tags": [ { "id": 2, "caption": "go程序员" } ] } ]

 

posted @ 2024-12-04 09:45  蜗牛·哥  阅读(3)  评论(0编辑  收藏  举报