一、序列化器基本概念

  • 序列化与反序列化

    • 反序列化:客户端传递过来数据,后端接受到数据之后,drf框架中的序列化器进行反序列化操作,把数据转换Django模型类定义的数据字段和类型(转换),然后把数据存储到数据库中(入库),转换和入库的过程就是反序列化过程。
    • 序列化:序列化器根据客户端的参数和请求从服务器获取到数据之后,把数据转换成JSON格式的数据并返回给客户端,转换的过程就是序列化过程
      (二)、定义序列化器规则
  • 导入serializers:from rest_framework import serializers

  • 定义类,继承自Serializer
  • 和模型类的字段名字一样
  • 和模型类的字段类型一样
  • 和模型类的字段选项一样
  • read_only=True必须定义,在序列化阶段需要用到 ```python “””模型类””” from django.db import models

    定义书籍模型类

    class BookInfo(models.Model): btitle = models.CharField(maxlength=20, verbosename=’名称’) bpub_date = models.DateField(verbose_name=”发布日期”) bread = models.IntegerField(default=0, verbose_name=”阅读量”) bcomment = models.IntegerField(default=0, verbose_name=”评论量”) is_delete = models.BooleanField(default=False, verbose_name=”逻辑删除”) class Meta: db_table = “tb_books” # 指明数据库表名 verbose_name = “图书” # 在admin站点中显示的名称 verbose_name_plural = verbose_name # 显示的复数名称 def __str(self): ‘’’定义每个数据对象的显示信息’’’ return self.btitle

“””序列化器””” from rest_framework import serializers

定义书籍的序列化器

class BookInfoSerializer(serializers.Serializer): id = serializers.IntegerField(read_only=True, label=”id”) btitle = serializers.CharField(max_length=20, label=”名称”) bpub_date = serializers.DateTimeField(label=”发布日期”) bread = serializers.IntegerField(default=0, label=”阅读量”) bcomment = serializers.IntegerField(default=0, label=”评论量”) is_delete = serializers.BooleanField(default=False, label=”逻辑删除”)

  1. <a name="ODEdo"></a>
  2. ##### (三)、序列化器的序列化使用<br />
  3. - 序列化单个模型类对象
  4. - 从数据库中获取到数据对象
  5. - 根据已经创建的序列化器类实例化序列化器对象,参数是:instance=数据对象
  6. - 序列化器对象.data获取基本的序列化后的结果
  7. ```python
  8. from .serializers import BookInfoSerializer
  9. from .models import BookInfo
  10. #序列化操作
  11. #获取书籍对象
  12. book = BookInfo.objects.get(id=5)
  13. #创建序列化器,instance表示需要将哪个对象进行序列化
  14. serializer = BookInfoSerializer(instance=book)
  15. # 转换数据
  16. print(serializer.data)
  • 序列化模型类列表对象
    • 从数据库中获取到数据对象列表
    • 根据已经创建的序列化器类实例化序列化器对象,参数是:instance=数据对象列表, many=True。注意:多个数据对象的时候必须在序列化器中添加many=True,否则会报错
    • 序列化器对象.data获取基本的序列化后的结果
  1. from book.models import BookInfo as BookInfoModel
  2. from book.serializers import BookInfoSerializer
  3. # 获取模型类数据对象
  4. books = BookInfoModel.objects.all()
  5. # 实例化序列化器对象
  6. serializer = BookInfoSerializer(instance=books, many=True)
  7. # 打印数据
  8. print(serializer.data)
  • 关联模型的序列化(模型类中有外键子段的模型关联被关联模型类)

    • 序列化器的创建中需要注意的地方:

      • 外键字段使用方式一(关联关联模型的主键):serializers.PrimaryKeyRelatedField(参数)

        • 方式一:参数写read_only=True
        • 方式二:导入关联字段的模型信息,在参数位置设置:queryset = 模型类.objects.all(),把模型类对象中的所有数据以数据集的形式传入
        • 如果不设置参数,程序会报错:AssertionError: Relational field must provide a queryset argument, override get_queryset, or set read_only=True.

          Note: 外键使用方式二(获取关联模型的str方法返回值):serializers.StringRelatedField(参数),参数的使用和上边的方式一或方式二一样,选择其中一个即可

      • 外键子段使用方式三:直接把关联模型的序列化器作为对内的内容写入,例如:hbook = BookInfoSerializer()。hbook是外键

    • 创建模型对象和序列化器实例对象,打印结果:
      • 关联主键的打印:字段信息是关联模型的主键/id数据
      • 关联str方法的打印:字段信息是关联模型类中定义好的str方法的返回值信息
  1. # 定义英雄的序列化器
  2. class HeroInfoSerializer(serializers.Serializer):
  3. GENDER_CHOICE = (
  4. (0, 'female'),
  5. (1, 'male')
  6. )
  7. id = serializers.IntegerField(read_only=True, label="id")
  8. hname = serializers.CharField(max_length=20, label="名称")
  9. hgender = serializers.ChoiceField(choices=GENDER_CHOICE, label="性别", required=False)
  10. # allow_null=True允许为空值
  11. hcomment = serializers.CharField(max_length=200, label="描述信息", required=False, allow_null=True)
  12. is_delete = serializers.BooleanField(default=False, label="逻辑删除")
  13. # 方式一:关联外键主键
  14. # hbook = serializers.PrimaryKeyRelatedField(read_only=True)
  15. # 方式二:关联外键子段的字符串信息__str__
  16. # hbook = serializers.StringRelatedField(read_only=True)
  17. # 方式三:关联BookInfoSerializer序列化器
  18. hbook = BookInfoSerializer()
  • 关联模型的序列化(被关联模型关联有外键子段的模型类)
    • 被关联模型类中没有设置外键
    • 如何查询被关联模型信息的时候,关联有外键子段的模型类,把对应的关联信息一并取出?
      • 方式一(关联主键):有外键子段的模型类名_set = serializers.ForeignKeyRelatedField(read_only=True, many=True)
      • 方式二(关联str方法):有外键子段的模型类名_set = serializers.StringRelatedField(read_only=True, many=True)

        Note:

        1. “有外键子段的模型类名”必须全部小写,不能采用驼峰命名,并且后边必须加上_set,单下划线,不是双下划线
        2. many=True:当出现要查询的结果不只一条的时候必须加上many=True,这在整个drf的序列化器中都是通用的,如果没有many=True程序就会报错
  1. from rest_framework import serializers
  2. from book.models import BookInfo as BookInfoModel
  3. # 定义书籍的序列化器
  4. class BookInfoSerializer(serializers.Serializer):
  5. id = serializers.IntegerField(read_only=True, label="id")
  6. btitle = serializers.CharField(max_length=20, label="名称")
  7. bpub_date = serializers.DateField(label="发布日期")
  8. bread = serializers.IntegerField(default=0, label="阅读量")
  9. bcomment = serializers.IntegerField(default=0, label="评论量")
  10. is_delete = serializers.BooleanField(default=False, label="逻辑删除")
  11. # 关联英雄类的主键
  12. # heroinfo_set = serializers.PrimaryKeyRelatedField(read_only=True, many=True)
  13. # 关联英雄模型__str__方法
  14. heroinfo_set = serializers.StringRelatedField(read_only=True, many=True)
  15. # 定义英雄的序列化器
  16. class HeroInfoSerializer(serializers.Serializer):
  17. GENDER_CHOICE = (
  18. (0, 'female'),
  19. (1, 'male')
  20. )
  21. id = serializers.IntegerField(read_only=True, label="id")
  22. hname = serializers.CharField(max_length=20, label="名称")
  23. hgender = serializers.ChoiceField(choices=GENDER_CHOICE, label="性别", required=False)
  24. hcomment = serializers.CharField(max_length=200, label="描述信息", required=False, allow_null=True)
  25. is_delete = serializers.BooleanField(default=False, label="逻辑删除")
  26. # 关联外键主键
  27. # hbook = serializers.PrimaryKeyRelatedField(read_only=True)
  28. # 关联外键子段的字符串信息__str__
  29. # hbook = serializers.StringRelatedField(read_only=True)
  30. #
  31. # 关联BookInfoSerializer
  32. hbook = BookInfoSerializer()

(四)、序列化器的反序列化使用
  • 校验:

    • 字段类型校验

      • IntegerField:整数
      • CharField:字符串
      • DateField:日期校验
      • BooleanField:布尔类型
      • 更多见文档……
        1. # 反序列化时使用data,序列化时使用instace
        2. serializer = BookInfoSerializer(data=book_dist)
        3. # raise_exception=True:如果校验不通过,则抛出异常信息
        4. serializer.is_valid(raise_exception=True)
        5. print(serializer.data)
    • 字段选项校验

      • max_length:最大长度
      • min_length:最小长度
      • required:false/true,默认为true,如果为false,可以不用传递该字段
      • default: 默认值,出现默认值的时候,该字段也可以不传递
      • Read_only:只读属性,默认为false,当为true的时候,反序列化的时候也可以不用传递该字段
    • 单字段校验(方法)

      • 校验方法名:validate_字段名,必须是这个格式的
      • 参数:self和value,value是这个字段传递过来的值
      • 校验方法必须写在模型类里
      • 校验不通过抛出异常:raise serializers.ValidationError(“错误信息提示内容”)
        1. def validate_btitle(self, value):
        2. if("西游" not in value):
        3. raise serializers.ValidationError("标题必须包含'西游'两个字")
        4. return value
    • 多字段校验(方法)

      • 应用场景:客户端传递过来的内容需要和数据库、缓存中的内容进行比对的字段必须用到多字段校验,例如:短信验证码、图片验证码等
      • 方法名:必须是validate
      • 参数:self和value,value可以是任意的名字,表示的是从客户端传递过来的所有数据
      • 校验方法必须写在模型类里
      • 校验不通过抛出异常:raise serializers.ValidationError(“错误信息提示内容”)
        1. # 多字段校验
        2. def validate(self, value):
        3. # value是客户端传递过来的所有的数据
        4. # 获取阅读量和评论量
        5. bread = value['bread']
        6. bcomment = value['bcomment']
        7. if(bread < bcomment):
        8. raise serializers.ValidationError("阅读量不能小于评论量")
        9. return value

        注意:无论是单字段还是多字段校验,校验成功的返回值必须是形参value,否则会报错

    • 自定义校验(方法)

      • 方法名:随意写,不受限制,但最好和校验的字段名相关
      • value是校验字段传递过来的数据值
      • 校验方法必须写在模型类的前边,否则程序会报找不到自定义方法的错误
      • 在需要校验的字段的参数重添加validators=[校验方法],需要注意的是,这是一个列表格式的,校验的方法可以有很多,并且校验的方法名直接写入,不能加引号
      • 如果校验失败报异常,如果校验成功,必须返回value参数 ```python

        自定义校验

        def check_bpub_date(value): if value.year <= 2018: raise serializers.ValidationError(“书籍的年份必须大于等于2018”) return value

校验字段

bpub_date = serializers.DateField(label=”发布日期”, validators=[check_bpub_date])

  1. - 入库
  2. - 情况一:创建新的对象(create)
  3. - 当使用序列化器.save()方法入库时,必须先在序列化器中重写create()方法,否则会报错:`create()` must be implemented
  4. - 重写create方法
  5. - 方法名:create()
  6. - 参数:selfvalidated_datavalidated_data必须是这个名字,表示已经校验过的数据
  7. - 方法内容:使用模型类中的create()方法来实现,参数是**validated_data
  8. - 返回值为:模型类对象
  9. ```python
  10. """序列化器中重写create()方法"""
  11. # 实现create方法
  12. def create(self, validated_data):
  13. # 创建book对象,设置属性,入库
  14. book = BookInfoModel.objects.create(**validated_data)
  15. # 返回
  16. return book
  17. """视图中"""
  18. # save()方法会去调用create()方法
  19. serializer.save()
  • 情况二:更新已有的对象(update)
    • 实例化序列化器,这里需要注意的是:参数必须是两个:instance=模型类对象、data=客户端传递的数据,这一点必须注意。序列户阶段,参数是instance,反序列化阶段的创建对象必须是data,但是反序列化阶段的更新必须是两个参数都得写上
    • 如果直接调用serializer.save()方法,程序会报update() must be implemented错误,所以,需要在模型类中重写update()方法
    • 重新update()方法
      • 参数:self,instance和validated_data
      • 方法内更新数据:instance.字段名 = validated_data[‘字段名’]
      • 执行更新操作:instance.save()
      • 返回值:return instance

        需要注意的是:因为是更新操作,更新需要知道是哪一条数据,所以instance代表的就是需要更新的数据对象

  1. """序列化器"""
  2. # 重写update()方法
  3. def update(self, instance, validated_data):
  4. # 更新数据
  5. instance.btitle = validated_data['btitle']
  6. instance.bpub_date = validated_data['bpub_date']
  7. instance.bread = validated_data['bread']
  8. instance.bcomment = validated_data['bcomment']
  9. # 入库
  10. instance.save()
  11. # 返回数据
  12. return instance
  13. """视图类"""
  14. # 更新某一条数据信息
  15. def put(self, request, pk):
  16. # 获取数据
  17. book_dict = json.loads(request.body.decode())
  18. # 实例化对象
  19. book = BookInfo.objects.get(id=pk)
  20. # 实例化序列化器
  21. serializer = BookInfoSerializer(instance=book, data=book_dict)
  22. serializer.is_valid(raise_exception=True)
  23. # save()方法调用的是序列化器中的update()方法
  24. serializer.save()
  25. return JsonResponse(serializer.data)