zoukankan      html  css  js  c++  java
  • ModelSerializer组件

    ModelSerializer组件

    1)序列化与反序列功能可以整合成一个类,该类继承ModelSerializer
    2)继承ModelSerializer类的资源序列化类,内部包含三部分
    Meta子类、局部钩子、全局钩子
    注:create和update方法ModelSerializer已经重写了,使用不需要重写
    3)在Meta子类中:
    用model来绑定关联的Model类
    用fields来设置所有的序列化反序列化字段
    用extra_kwargs来设置系统的校验规则
    4)重要的字段校验规则:
    read_only校验规则,代表该字段只参与序列化
    write_only校验规则,代表该字段只参与反序列化
    required校验规则,代表该字段在反序列化是是否是必填(True)还是选填(False),不能和read_only一起使用(规则冲突)
    规则细节:
    如果一个字段有默认值或是可以为空,没设置required规则,默认为False,反之默认值为True
    如果一个Model字段即没有设置read_only也没设置write_only,该字段默认参与序列化及反序列化
    5)自定义序列化字段:在Model类中,定义方法属性(可以返回特殊值,还可以完成连表操作),在序列化类的fields属性中可以选择性插拔
    6)自定义反序列化字段:在Serializer类中,自定义校验字段,校验规则也只能在声明字段时设置,自定义的反序列化字段(如re_pwd),
    必须设置write_only为True

    from rest_framework.serializers import ModelSerializer
    from . import models
    # 整合序列化与反序列化
    class UserModelSerializer(ModelSerializer):
        # 将序列化类与Model类进行绑定
        # 设置序列化与反序列化所有字段(并划分序列化字段与反序列化字段)
        # 设置反序列化的局部与全局钩子
    
        # 自定义反序列化字段,校验规则只能在声明自定义反序列化字段时设置,且一定是write_only
        re_pwd = serializers.CharField(min_length=3, max_length=64, write_only=True)
    
        class Meta:
            model = models.User
            # 序列化
            fields = ['name', 'age', 'height', 'gender', 'pwd', 're_pwd']
            # 反序列化
            extra_kwargs = {
                'name': {
                    'required': True,
                    'min_length': 3,
                    'error_messages': {
                        'min_length': '太短'
                    }
                },
                'age': {
                    'required': True,  # 数据库有默认值或可以为空字段,required默认为False
                    'min_value': 0
                },
                'pwd': {
                    'required': True,
                    'write_only': True,  # 只参与反序列化
                },
                'gender': {
                    'read_only': True,  # 只参与序列化
                },
            }
    
        def validate_name(self, value):
            if 'g' in value.lower():
                raise serializers.ValidationError('名字中不能有g')
            return value
    
        def validate(self, attrs):
            pwd = attrs.get('pwd')
            re_pwd = attrs.pop('re_pwd')
            if pwd != re_pwd:
                raise serializers.ValidationError({'re_pwd': '两次密码不一致'})
            return attrs
    
        # ModelSerializer已经帮我们重写了入库方法
    
        # 自定义插拔序列化字段:替换了在Serializer类中自定义的序列化字段(SerializerMethodField)
        # 自定义插拔序列化字段一定不参与反序列化过程
        @property
        def gender(self):
            return self.get_sex_display()
    
    from rest_framework.views import APIView
    from rest_framework.response import Response
    from . import models, serializers
    from rest_framework import status
    class UserV2APIView(APIView):
        # 单查群查
        def get(self, request, *args, **kwargs):
            pk = kwargs.get('pk')
            if pk:
                user_obj = models.User.objects.filter(pk=pk).first()
                if not user_obj:
                    return Response({
                        'status': 1,
                        'msg': '单查 error'
                    })
    
                # 完成序列化
                user_data = serializers.UserModelSerializer(user_obj, many=False).data
    
                return Response({
                    'status': 0,
                    'msg': '单查 ok',
                    'results': user_data
                })
    
            # 群查
            user_query = models.User.objects.all()
            # 完成序列化
            user_list_data = serializers.UserModelSerializer(user_query, many=True).data
            return Response({
                'status': 0,
                'msg': '群查 ok',
                'results': user_list_data
            })
    
        # 单增
        def post(self, request, *args, **kwargs):
            request_data = request.data
    
            user_ser = serializers.UserModelSerializer(data=request_data)
    
            # 校验失败,直接抛异常,反馈异常信息给前台,只要校验通过,代码才会往下执行
            result = user_ser.is_valid()
            if result:
                user_obj = user_ser.save()
                return Response({
                    'status': 0,
                    'msg': 'ok',
                    'results': serializers.UserModelSerializer(user_obj).data
                })
            else:
                # 校验失败,返回错误信息
                return Response({
                    'status': 1,
                    'msg': user_ser.errors
                }, status=status.HTTP_400_BAD_REQUEST)
    
    
    

    模型类序列化器

    如果我们想要使用序列化器对应的是Django的模型类,DRF为我们提供了ModelSerializer模型类序列化器来帮助我们快速创建一个Serializer类。

    ModelSerializer与常规的Serializer相同,但提供了:

    • 基于模型类自动生成一系列字段
    • 基于模型类自动为Serializer生成validators,比如unique_together
    • 包含默认的create()和update()的实现

    定义

    比如我们创建一个BookInfoSerializer

    class BookInfoSerializer(serializers.ModelSerializer):
        """图书数据序列化器"""
        class Meta:
            model = BookInfo
            fields = '__all__'
    
    • model 指明参照哪个模型类
    • fields 指明为模型类的哪些字段生成

    我们可以在python manage.py shell中查看自动生成的BookInfoSerializer的具体实现

    >>> from booktest.serializers import BookInfoSerializer
    >>> serializer = BookInfoSerializer()
    >>> serializer
    BookInfoSerializer():
        id = IntegerField(label='ID', read_only=True)
        btitle = CharField(label='名称', max_length=20)
        bpub_date = DateField(allow_null=True, label='发布日期', required=False)
        bread = IntegerField(label='阅读量', max_value=2147483647, min_value=-2147483648, required=False)
        bcomment = IntegerField(label='评论量', max_value=2147483647, min_value=-2147483648, required=False)
        image = ImageField(allow_null=True, label='图片', max_length=100, required=False)
    

    指定字段

    1. 使用fields来明确字段,__all__表名包含所有字段,也可以写明具体哪些字段,如
    class BookInfoSerializer(serializers.ModelSerializer):
        """图书数据序列化器"""
        class Meta:
            model = BookInfo
            fields = ('id', 'btitle', 'bpub_date')
    
    1. 使用exclude可以明确排除掉哪些字段
    class BookInfoSerializer(serializers.ModelSerializer):
        """图书数据序列化器"""
        class Meta:
            model = BookInfo
            exclude = ('image',)
    
    1. 显示指明字段,如:
    class HeroInfoSerializer(serializers.ModelSerializer):
        hbook = BookInfoSerializer()
    
        class Meta:
            model = HeroInfo
            fields = ('id', 'hname', 'hgender', 'hcomment', 'hbook')
    
    1. 指明只读字段

    可以通过read_only_fields指明只读字段,即仅用于序列化输出的字段

    class BookInfoSerializer(serializers.ModelSerializer):
        """图书数据序列化器"""
        class Meta:
            model = BookInfo
            fields = ('id', 'btitle', 'bpub_date', 'bread', 'bcomment')
            read_only_fields = ('id', 'bread', 'bcomment')
    
    

    添加额外参数

    我们可以使用extra_kwargs参数为ModelSerializer添加或修改原有的选项参数

    class BookInfoSerializer(serializers.ModelSerializer):
        """图书数据序列化器"""
        class Meta:
            model = BookInfo
            fields = ('id', 'btitle', 'bpub_date', 'bread', 'bcomment')
            extra_kwargs = {
                'bread': {'min_value': 0, 'required': True},
                'bcomment': {'min_value': 0, 'required': True},
            }
    
    # BookInfoSerializer():
    #    id = IntegerField(label='ID', read_only=True)
    #    btitle = CharField(label='名称', max_length=20)
    #    bpub_date = DateField(allow_null=True, label='发布日期', required=False)
    #    bread = IntegerField(label='阅读量', max_value=2147483647, min_value=0, required=True)
    #    bcomment = IntegerField(label='评论量', max_value=2147483647, min_value=0, required=True)
    
    
  • 相关阅读:
    Mybatis和Spring整合也是能用BatchExecutor的
    与Spring整合的Mybatis没法真正使用BatchExecutor
    Mybatis和Spring整合后sqlsession啥时候关闭的
    Mybatis和Spring的整合原理
    Mybatis是怎么执行一条语句的
    8.11查询结果排序
    8.10、11(select分组和过滤)()
    8.7、8、9(select语句基本用法)(select语句基本运算符)(select聚合查询)
    8.4SQL(DML数据操作语言)-(insert插入数据)(updata更新数据),(delete数据)
    8.2数据库DDL语言(即数据库定义语言)(命名规则以及数据类型)
  • 原文地址:https://www.cnblogs.com/SkyOceanchen/p/11901815.html
Copyright © 2011-2022 走看看