zoukankan      html  css  js  c++  java
  • 定义序列化器之关联属性(一对多、多对多)

    定义序列化器,通常是拿模型类的代码过来修改一下。但是如果遇到有关联属性的时候,应该怎么写呢?

    假设有两个模型类,一个是员工,一个是部门。部门与员工是一对多关系。那么在定义序列器的时候怎么写关联属性的语句呢?

    先把没有涉及关联属性的字段写成序列化器:

    from rest_framework import serializers
    
    
    class DepartmentSerializer(serializers.Serializer):
        """部门序列化器类"""
        id = serializers.IntegerField(read_only=True)
        name = serializers.CharField(max_length=20)
        create_date = serializers.DateField()class EmployeeSerializer(serializers.Serializer):
        """员工序列化器"""
    
        choices_gender = (
            (0, ''),
            (1, ''),
        )
    
        name = serializers.CharField(max_length=20)
        age = serializers.IntegerField()
        gender = serializers.ChoiceField(default=0, choices=choices_gender)
        salary = serializers.DecimalField(max_digits=8, decimal_places=2)
        comment = serializers.CharField(max_length=300)
        hire_date = serializers.DateField()
    • 一对多关系中,多的那方的序列化器关联属性的写法:

    如果我要对员工对象序列化时有这样的效果:

    # 第一种效果
    { "name": "赵小一",
        ..., "department": 1, # 第1种:PrimaryKeyRelatedField }

    # 第二种效果 { "name": "赵小一",
        ..., "department": "研发部", # 第2种:StringRelatedField }

    # 第三种效果 { "name": "赵小一",
        ..., "department": { # 第3种:DepartmentSerializer "id": 1, "name": "研发部", "create_date": "2018-1-1" } }

    员工序列化器的定义如下:

    class EmployeeSerializer(serializers.Serializer):
        """员工序列化器"""
    
        choices_gender = (
            (0, ''),
            (1, ''),
        )
    
        name = serializers.CharField(max_length=20)
        age = serializers.IntegerField()
        gender = serializers.ChoiceField(default=0, choices=choices_gender)
        salary = serializers.DecimalField(max_digits=8, decimal_places=2)
        comment = serializers.CharField(max_length=300)
        hire_date = serializers.DateField()
        # 定义序列化器时关联属性的设置
        # 1.1 返回关联属性的主键,设置属性为read_only=True表示修改时,即使传过来的员工信息有部门的id,也不做修改,保留原始的值!
        department = serializers.PrimaryKeyRelatedField(read_only=True)
        # 1.2 返回关联属性的主键,设置属性为查询集,表示修改时,当你要修改部门时,如果查询集有,可以修改,如果没有,不可以修改!
        department = serializers.PrimaryKeyRelatedField(queryset=Department.objects.all())
        # 2 返回关联属性的类的__str__方法的值。如果我们想要返回部门的名称,可以在model里面增加__str__方法返回部门名称
        department = serializers.StringRelatedField()
        # 3 返回关联属性的所有属性值时,可以这样写:
        department = DepartmentSerializer()
    • 一对多关系中,一的那方的序列化器关联属性的写法:(多对多关系的两边都可以这样写

    部门序列化器的定义如下:

    class DepartmentSerializer(serializers.Serializer):
        """部门序列化器类"""
        id = serializers.IntegerField(read_only=True)
        name = serializers.CharField(max_length=20)
        create_date = serializers.DateField()
        is_delete = serializers.BooleanField(default=False)
        # 返回关联属性的主键,因为有多个,所以必须加上many=True
        employee_set = serializers.PrimaryKeyRelatedField(read_only=True,many=True)
        # 返回关联属性的类的__str__方法的值。如果我们想要返回员工的名字,可以在model里面增加__str__方法返回员工的名字。
        employee_set = serializers.StringRelatedField(many=True)
        # 返回关联属性的所有属性值
        employee_set = EmpSerializer(many=True)

    注意:因为一的这方序列化时会出现多条关联属性,所以必须加上many=True。

     

    • 一个小小的坑

    如果在一个文件中,定义了员工和部门的序列化器,并且,两个序列化器都返回关联属性的所有属性值时:

    部门序列化器有这句语句:

    employee = EmployeeSerializer(many = True)

    员工序列化器有这句语句:

    department = DepartmentSerializer()

    此时会出现相互引用的情况,导致出错!

    解决办法:

    在部门序列化器前再加多一个员工序列化器,并且把department = DepartmentSerializer()删掉!

  • 相关阅读:
    PHP 面试踩过的坑(三)
    明天准备离职了,面对照顾自己的领导,要这样说
    别怕!MySQL引起的CPU消耗过大,我有办法
    值得收藏:一份非常完整的 MySQL 规范(一)
    emacs 快捷键设置 基础知识篇
    Ruby快速入门(三):控制语句
    Ruby快速入门(一):安装、运行、类和对象
    Ruby快速入门(二):变量、数字、数组和运算符
    Ruby快速入门(四):类和模块
    emacs安装autocomplete插件
  • 原文地址:https://www.cnblogs.com/chichung/p/9937176.html
Copyright © 2011-2022 走看看