美文网首页
DRF使用篇(五):序列化器ModelSerializer

DRF使用篇(五):序列化器ModelSerializer

作者: 是立品啊 | 来源:发表于2020-07-13 21:31 被阅读0次

    如果想为Django存在的模型类快速创建序列化器,可以使用DRF框架封装好的ModelSerializer模型类序列化器来帮助我们快速创建一个Serializer类

    • 基于模型类的字段条件创建约束
    • 内部已经封装了create与update方法,序列化器对象在调用save()方法时,会自动对数据库进行操作

    指定全字段

    # 继承自serializers.ModelSerializer
    class StudentInfoSerializer(serializers.ModelSerializer)
        class Meta:
            model = StudentInfo # 指定要依据的模型类
            fields = '__all__' # 设置全部字段自动生成
    

    自定义过滤字段

    • 使用fields来明确字段, 可以写明具体哪些字段
    # 继承自serializers.ModelSerializer
    class StudentInfoSerializer(serializers.ModelSerializer)
    class Meta:
        model = StudentInfo # 指定要依据的模型类
        fields = ['id', 'name'] # 列表中设置指定要生成的字段
    
    • 使用exclude可以明确排除掉哪些字段
    # 继承自serializers.ModelSerializer
    class StudentInfoSerializer(serializers.ModelSerializer):
        class Meta:
            model = StudentInfo # 指定要依据的模型类
            exclude = ['info'] # 指定哪些字段不需要自动生成
    
    • 通过read_only_fields指明只读字段,即仅用于序列化输出的字段
    # 继承自serializers.ModelSerializer
    class StudentInfoSerializer(serializers.ModelSerializer):
        class Meta:
            model = StudentInfo # 指定要依据的模型类
            fields = '__all__' # 自定生成全部字段
            read_only_fields = ['id', 'name'] # 指定列表中的字段仅用于序列化操作
    
    • extra_kwargs参数为ModelSerializer添加或修改原有的选项参数
    # 继承自serializers.ModelSerializer
    class StudentInfoSerializer(serializers.ModelSerializer):
        class Meta:
            model = StudentInfo # 指定要依据的模型类
            fields = '__all__' # 设置全部字段自动生成
            extra_kwargs  = {
            name: { # 给name字段设置额外的约束
                'min_value': 0, # 设置最小的长度
                'required': True # 设置是否必传
                }
            info: { # 同上
                'min_value': 0,
                'required': True
                }
            }
    

    外键

    # 班级模型类
    class ClassInfo(models.Model):
        name = models.CharField(max_length=20, verbose_name='班级名称')
        Info = models.CharField(max_length=20, verbose_name='班级信息')
    
        class Meta:
            db_table = 'class'
        def __str__(self):
            return self.name
    
    # 学生模型类
    class StudentInfo(models.Model):
        name = models.CharField(max_length=20, verbose_name='姓名')
        clsinfo = models.ForeignKey(ClassInfo, related_name='cls_stu)
    
        class Meta:
            db_table = 'student'
        def __str__(self):
            return self.name
    

    那么在 Django REST framework 我们通常按下面的方式定义 Serializer 类. 在 ClassInfo 类中增加一个属性 cls_stu(student外键到class的别名) 来保存当前 class 对象所有的学生集合. 但是此时有个问题如果此 Class 对象所拥有的Student 比较多, 此时就会影响性能. 比如:

    # 班级序列化器
    class ClassSerializer(serializers.ModelSerializer):
        cls_stu = serializers.PrimaryKeyRelatedField(many=True, required=False, read_only=True)
    
        class Meta:
            model = Article
            fields = ('id', 'name', 'info', 'cls_stu')
    
    # 学生序列化器
    class StudentSerializer(serializers.ModelSerializer):
        class Meta:
            model = Comment
            fields = ('id', 'name', 'clsinfo')
    
    1. 但是这样会出现一个问题: 这样序列化Class 对象的时候会把 所有与 Clas 对象关联的 student 对象的也序列化起来,就算是我们用 IntegerField 或者 StringRelatedField 那也会序列化很多用户的信息

    2. 其实在很多时候我们并不需要在查询 Class 对象的时候查询所拥有的 Student对象,很多时候我们只是需要一个 Class 所拥有 Student对象的总数就可以了,如果有需要再去查询Student 列表详细。此时我们就可以使用Django REST framework 提供的 SerializerMethodField 来实现这个目的

    # 班级序列化器
    class ClassSerializer(serializers.ModelSerializer):
         get_cls_stu_count = serializers.SerializerMethodField()
    
        class Meta:
            model = Article
            fields = ('id', 'name', 'info', 'get_cls_stu_count')
        def get_cls_stu_count(self, obj):
            return obj.cls_stu.all().count()
    
    # 学生序列化器
    class StudentSerializer(serializers.ModelSerializer):
        class Meta:
            model = Comment
            fields = ('id', 'name', 'clsinfo')
    
    1. 首先在 ClassSerializer 中去除cls_stu 属性
    2. 然后在 ClassSerializer 中增加一个属性 get_cls_stu_count, 并把这个属性添加到Metafields列表里
    3. 添加一个 get_cls_stucount方法,这个方法的命名规则就是在上面声明的属性前面加上个'get'前缀,并接受一个 obj参数,这个obj参数就是当前的 ClassInfo 对象实例。

    相关文章

      网友评论

          本文标题:DRF使用篇(五):序列化器ModelSerializer

          本文链接:https://www.haomeiwen.com/subject/bjgzcktx.html