当前位置:   article > 正文

DRF之序列化组件

DRF之序列化组件

目录

一、序列化组件介绍

二、序列化类的使用

三、序列化类快速使用

四、 序列化类反序列化校验

【使用步骤】 

五、序列化类保存和修改

【保存】

【修改】

六、常用序列化字段和参数

【1】常用字段

【2】常用参数

七、序列化高级用法之soruce

八、序列化高级用法之定制返回字段

【1】多表关联序列化

【2】多表关联反序列化

九、ModelSerializer使用


一、序列化组件介绍

序列化类(组件)可以干的事:

  1. 序列化 qs对象,单个对象 做序列化给前端
  2. 反序列化数据校验:前端传入数据---> 校验数据是否合法
  3. 反序列化---> 前端传入数据,存到数据库中
  • DRF(Django REST framework)是一个用于构建基于 Django 的 Web API 的强大框架。
    • 在 DRF 中,序列化组件是其中一个核心组件,用于在 API 请求和响应中处理数据的转换和验证。
  • 序列化组件的主要功能是将复杂的数据结构(例如模型对象)转换为可以序列化(序列化为 JSON、XML 等格式)和传输的数据,并且能够根据所需的数据结构对传入的数据进行反序列化,还原为程序可操作的对象。

二、序列化类的使用

1 写个py文件,叫serializer.py
2 写个类,继承serializers.Serializer
3 在类中写要序列化的字段

  1. from rest_framework import serializers
  2. class PublishSerializer(serializers.Serializer):
  3. # 写字段,要序列化的字段
  4. name = serializers.CharField()
  5. addr = serializers.CharField()
  6. id = serializers.IntegerField()

4 在视图类中使用,完成序列化

  1. 多条
  2. ser = PublishSerializer(instance=publish_list, many=True)      
  3. ser.data  # 序列化后的数据
  4. 单条:
  5. ser = PublishSerializer(instance=publish)      
  6. ser.data  # 序列化后的数据
  • 参数
    • instance : 实例(对象)
    • data : 数据
    • many=True : 如果是queryset对象,一般都是必须加
    • many=False : 如果是 .first() 一般不写,默认不写是 False
  • 序列化的结果
    • data = book_ser.data
      • 将 book_ser 转成字典 -- 列表套字典
    • data的类型是
      • <class 'rest_framework.utils.serializer_helpers.ReturnList'>

三、序列化类快速使用

视图类

  1. from .serializer import PublishSerializer
  2. class PublishView(APIView):
  3. def get(self, request):
  4. publish_list = Publish.objects.all()
  5. ser = PublishSerializer(instance=publish_list, many=True)
  6. # 如果序列化多条,要many=True
  7. return Response({'code': 100, 'msg': '查询所有成功', 'results': ser.data})
  8. class PublishDetailView(APIView):
  9. def get(self, request, pk):
  10. publish = Publish.objects.filter(pk=pk).first()
  11. ser = PublishSerializer(instance=publish) # 单个不写many=True
  12. return Response(
  13. {'code': 100, 'msg': '查询单条成功', 'results': ser.data})

序列化类

  1. from rest_framework import serializers
  2. class PublishSerializer(serializers.Serializer):
  3. # 写字段,要序列化的字段
  4. name = serializers.CharField()
  5. # addr = serializers.CharField()
  6. id = serializers.IntegerField()

路由

  1. urlpatterns = [
  2. path('publish/', views.PublishView.as_view()),
  3. path('publish/<int:pk>', views.PublishDetailView.as_view()),
  4. ]

四、 序列化类反序列化校验

序列化类可以做字段校验---> 三层
第一层:字段自己的serializers.CharField(max_length=12,min_length=3)

第二层:局部钩子

  1. def validate_name(self, name):
  2. # 待校验的前端传入的name的数据
  3. if name.startswith("sb"):
  4. # 不行,抛异常
  5. raise ValidationError('不能以sb开头')
  6. return name

全局钩子--> 前端多传的,这里不会有

  1. def validate(self, attrs):
  2. print(attrs)
  3. # 多个字段同时校验
  4. # 出版社名和地址不能一样---》出版社前3个字不能和地址前3个字一样
  5. if attrs.get('name')[:3] == attrs.get('addr')[:3]:
  6. raise ValidationError('出版社名和地址不能一样')
  7. return attrs

【使用步骤】 

写序列化类:写三层规则

视图类中:

  1. ser = PublishSerializer(data=request.data)  # 把待校验数据传入
  2. if ser.is_valid():  # 做数据校验---> 三层
  3. print(ser.data)
  4. else:
  5. print(ser.errors)  # 没有校验通过,打印错误信息

五、序列化类保存和修改

【保存】

1 在序列化类中,必须重写 create,完成真正的保存

  1. """保存,必须重写create"""
  2. def create(self, validated_data):
  3. # validated_data 校验过后的数据---》多传的数据,在这没有
  4. publish = Publish.objects.create(**validated_data)
  5. return publish  
  6. # 不要忘了返回新增的对象---> 后续会拿着这个对象做序列化  ser.data--->根据它做序列化的

2 在视图类中,数据校验通过后,调用ser.save()
ser.save()  # 使用序列化类保存--> 会报错---> 我们没有指定保存到那个表--> 必须重写create方法

【修改】

修改功能,也要校验和保存

1 在序列化类中,必须重写 update,完成真正的修改

  1. def update(self, instance, validated_data):  # {name:上海出版社,add:上海地址}
  2. instance.name = validated_data.get('name')
  3. instance.addr = validated_data.get('addr')
  4. instance.save() # publish 对象的save---> 保存到数据中
  5. return instance


2 视图类中
        ser = PublishSerializer(instance=publish, data=request.data)
        ser.save() # 虽然新增或修改都是调用save,但是内部做了判断

六、常用序列化字段和参数

【1】常用字段

字段字段构造方式详解
BooleanFieldBooleanField()布尔字段用于存储和表示真/假值。构造方法不需要参数。
NullBooleanFieldNullBooleanField()可空布尔字段是可以接受三个值的布尔字段:True、False和None(空值)。构造方法不需要参数。
CharFieldCharField(max_length=None, min_length=None, allow_blank=False, trim_whitespace=True)字符字段用于存储短文本数据。max_length指定字符的最大长度,min_length指定最小长度。allow_blank指定是否允许为空值。trim_whitespace指定是否在保存数据前去除首尾的空格。
EmailFieldEmailField(max_length=None, min_length=None, allow_blank=False)Email字段用于存储和验证电子邮件地址。max_length指定最大字符长度,min_length指定最小长度。allow_blank指定是否允许为空值。
RegexFieldRegexField(regex, max_length=None, min_length=None, allow_blank=False)正则表达式字段用于存储和验证符合特定模式的数据。regex指定正则表达式,max_length指定最大字符长度,min_length指定最小长度。allow_blank指定是否允许为空值
SlugFieldSlugField(maxlength=50, min_length=None, allow_blank=False) 正则字段,验证正则模式 [a-zA-Z0-9-]+Slug字段用于存储URL友好的文本标识符。max_length指定最大字符长度,min_length指定最小长度。allow_blank指定是否允许为空值。
URLFieldURLField(max_length=200, min_length=None, allow_blank=False)URL字段用于存储和验证URL地址。max_length指定最大字符长度,min_length指定最小长度。allow_blank指定是否允许为空值。
UUIDFieldUUIDField(format=’hex_verbose’) format: 1) 'hex_verbose' 如"5ce0e9a5-5ffa-654b-cee0-1238041fb31a" 2) 'hex' 如 "5ce0e9a55ffa654bcee01238041fb31a" 3)'int' - 如: "123456789012312313134124512351145145114" 4)'urn' 如: "urn:uuid:5ce0e9a5-5ffa-654b-cee0-1238041fb31a"UUID字段用于存储和验证通用唯一标识符。format参数指定UUID的格式。
IPAddressFieldIPAddressField(protocol=’both’, unpack_ipv4=False, **options)IP地址字段用于存储和验证IP地址。protocol参数指定所允许的IP地址协议类型,unpack_ipv4参数指定是否拆分IPv4地址。
IntegerFieldIntegerField(max_value=None, min_value=None)整数字段用于存储整数值。max_value指定最大值,min_value指定最小值。
FloatFieldFloatField(max_value=None, min_value=None)浮点数字段用于存储浮点数值。max_value指定最大值,min_value指定最小值。
DecimalFieldDecimalField(max_digits, decimal_places, coerce_to_string=None, max_value=None, min_value=None) max_digits: 最多位数 decimal_palces: 小数点位置十进制字段用于存储精确的十进制数值。max_digits指定最多位数,decimal_places指定小数点位置。coerce_to_string指定是否将值强制转化为字符串形式。max_value指定最大值,min_value指定最小值。
DateTimeFieldDateTimeField(format=api_settings.DATETIME_FORMAT, input_formats=None)日期时间字段用于存储日期和时间。format参数指定日期时间的输出格式,input_formats参数指定输入格式。
DateFieldDateField(format=api_settings.DATE_FORMAT, input_formats=None)日期字段用于存储日期。format参数指定日期的输出格式,input_formats参数指定输入格式。
TimeFieldTimeField(format=api_settings.TIME_FORMAT, input_formats=None)时间字段用于存储时间。format参数指定时间的输出格式,input_formats参数指定输入格式。
DurationFieldDurationField()持续时间字段用于存储一段时间的持续时间。构造方法不需要参数。
ChoiceFieldChoiceField(choices) choices与Django的用法相同选择字段用于存储和验证预定义选项中的一个值。choices参数指定可选的选项值。
MultipleChoiceFieldMultipleChoiceField(choices)多选字段用于存储和验证多个预定义选项中的值。choices参数指定可选的选项值。
FileFieldFileField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)文件字段用于上传和保存文件。max_length指定文件名的最大长度,allow_empty_file指定是否允许为空文件。use_url指定是否使用文件的URL路径。
ImageFieldImageField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)图片字段用于上传和保存图片文件。max_length指定文件名的最大长度,allow_empty_file指定是否允许为空文件。use_url指定是否使用图片的URL路径。
ListFieldListField(child=, min_length=None, max_length=None)列表字段用于存储和验证列表类型的数据。child参数指定列表中元素的类型,min_length指定最小长度,max_length指定最大长度。
DictFieldDictField(child=)字典字段用于存储和验证字典类型的数据。child参数指定字典中value的类型。
  • 总结:常用字段
  1. IntegerField
  2. CharField
  3. DateTimeField
  4. DecimalField
  5. ListField和DictField

【2】常用参数

(1) 选项参数:(CharField,IntegerField)

参数名称作用
max_length校验,最大长度
min_lenght检验,最小长度
allow_blank是否允许为空
trim_whitespace去掉前后的空白
max_value最小值
min_value最大值

(2) 通用参数

  1. read_only 表明该字段仅用于序列化输出,默认False
  2. write_only 表明该字段仅用于反序列化输入,默认False
  3. -------------------------------------------------------
  4. required 表明该字段在反序列化时必须输入,默认True
  5. default 反序列化时使用的默认值
  6. allow_null 表明该字段是否允许传入None,默认False
  7. validators 该字段使用的验证器:validators=[方法],方法对该字段做校验
  8. error_messages 包含错误编号与错误信息的字典
  9. ---------------
  10. label 用于HTML展示API页面时,显示的字段名称
  11. help_text 用于HTML展示API页面时,显示的字段帮助提示信息
  • 常用参数
  1. read_only
  2. write_only

七、序列化高级用法之soruce

1 修改字段,映射字段

  1. # publish_name表中不存在
  2. publish_name = serializers.CharField(source='name')

2 修改字段,映射方法

  1. # sb_name是表模型中一个方法
  2. name = serializers.CharField(source='sb_name')

3 修改字段,跨表查询

  1. # book表中可以链表查询
  2. publish=models.ForeignKey(to='Publish.name')

八、序列化高级用法之定制返回字段

【1】多表关联序列化

  1. # 定制序列化返回的字段格式
  2. -方案一:在表模型中写,在序列化类中映射 (可以使用source)
  3. # models.py
  4. def publish_detail(self):
  5. return {'name': self.publish.name, 'city': self.publish.city}
  6. # serializer.py
  7. publish_detail = serializers.DictField()
  8. # 前端看到
  9. "publish_detail": {
  10. "name": "北京出版社",
  11. "city": "北京"
  12. }
  13. -方案二:在序列化类中写SerializerMethodField,必须配合一个方法 get_字段名,方法返回什么,前端就看到什么
  14. # Serializer.py
  15. publish_detail = serializers.SerializerMethodField()
  16. def get_publish_detail(self, obj):
  17. return {'name': obj.publish.name, 'city': obj.publish.city}
  18. # 前端看到
  19. "publish_detail": {
  20. "name": "北京出版社",
  21. "city": "北京"
  22. }

models.py

  1. from django.db import models
  2. class Book(models.Model):
  3. name = models.CharField(max_length=32)
  4. price = models.DecimalField(max_digits=5, decimal_places=2)
  5. publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE)
  6. authors = models.ManyToManyField(to='Author')
  7. def __str__(self):
  8. return self.name
  9. # def book_name(self):
  10. # return self.name+'sb'
  11. # def publish_detail(self):
  12. # return {'name': self.publish.name, 'city': self.publish.city}
  13. #
  14. # def author_list(self):
  15. # l = []
  16. # for author in self.authors.all():
  17. # l.append({'name': author.name, 'age': author.age})
  18. # return l
  19. class Author(models.Model):
  20. name = models.CharField(max_length=32)
  21. age = models.IntegerField()
  22. author_detail = models.OneToOneField(to='AuthorDetail', on_delete=models.CASCADE)
  23. def __str__(self):
  24. return self.name
  25. class AuthorDetail(models.Model):
  26. telephone = models.BigIntegerField()
  27. birthday = models.DateField()
  28. addr = models.CharField(max_length=64)
  29. class Publish(models.Model):
  30. name = models.CharField(max_length=32)
  31. city = models.CharField(max_length=32)
  32. email = models.EmailField()
  33. def __str__(self):
  34. return self.name
  35. class Meta:
  36. verbose_name = '出版社'
  37. verbose_name_plural = verbose_name

views.py

  1. class BookView(APIView):
  2. def get(self, request):
  3. obj = Book.objects.all()
  4. ser = BookSerializer(instance=obj, many=True)
  5. '''
  6. [
  7. {
  8. "name": "西游记",
  9. "price": "66.00",
  10. "publish_detail": {name:名字,city:城市},
  11. "authors_list":[{name:名字,age:19}]
  12. },
  13. ]
  14. '''
  15. return Response(ser.data)
  1. ### 定制返回字段 ###
  2. class BookSerializer(serializers.Serializer):
  3. name = serializers.CharField()
  4. price = serializers.CharField()
  5. # 定制返回字段---》方案一:在表模型中写方法,在序列化类中做映射
  6. # publish_detail = serializers.CharField() # publish_detail 会映射表模型中 publish_detail方法,方法返回值是 字典,强行用CharField字符串接收
  7. # publish_detail = serializers.DictField() # publish_detail 会映射表模型中 publish_detail方法,方法返回值是 字典,用DictField接收
  8. # author_list = serializers.ListField()
  9. # 定制返回字段---》方案二:在序列化类中写 SerializerMethodField
  10. # 只要写了这个字段类SerializerMethodField,必须配合一个方法:get_字段名,这个方法返回什么,前端这个字段就显示什么
  11. publish_detail = serializers.SerializerMethodField()
  12. def get_publish_detail(self, obj):
  13. # 当前序列化到的book对象
  14. return {'name': obj.publish.name, 'city': obj.publish.city}
  15. author_list = serializers.SerializerMethodField()
  16. def get_author_list(self, obj):
  17. l = []
  18. for author in obj.authors.all():
  19. l.append({'name': author.name, 'age': author.age})
  20. return l
  21. book_name = serializers.SerializerMethodField()
  22. def get_book_name(self, obj):
  23. return obj.name + 'sb'

【2】多表关联反序列化

反序列化保存
使用同一个序列化类会出现

  • 序列化字段和反序列化字段不一致
  • 序列化字段:
    • name
    • price
    • publish_detail
    • author_list
  • 反序列化字段:
    • name
    • price
    • publish
    • author
  • 如果是共同的,不需要额外处理
  • 如果是不同的,需要通过字段参数控制
    • read_only    表明该字段仅用于序列化输出,默认False,序列化过程
    • write_only    表明该字段仅用于反序列化输入,默认False,反序列化过程

serializer.py

  1. class BookSerializer(serializers.Serializer):
  2. name = serializers.CharField() # 公共的
  3. price = serializers.CharField() # 公共的
  4. publish = serializers.IntegerField(write_only=True) # 只用来做反序列化
  5. authors = serializers.ListField(write_only=True) # 只用来做反序列化
  6. publish_detail = serializers.SerializerMethodField(read_only=True) # 只用来做序列化
  7. author_list = serializers.SerializerMethodField(read_only=True) # 只用来做序列化
  8. def get_publish_detail(self, obj):
  9. return {'name': obj.publish.name, 'city': obj.publish.city}
  10. def get_author_list(self, obj):
  11. l = []
  12. for author in obj.authors.all():
  13. l.append({'name': author.name, 'age': author.age})
  14. return l
  15. def create(self, validated_data):
  16. # {name,price,publish:1,authors:[1,2]}
  17. authors = validated_data.pop('authors')
  18. book = Book.objects.create(name=validated_data.get('name'), price=validated_data.get('price'),
  19. publish_id=validated_data.get('publish'))
  20. book.authors.add(*authors)
  21. return book
  22. def update(self, instance, validated_data):
  23. # {name,price,publish:1,authors:[1,2]}
  24. authors = validated_data.pop('authors')
  25. validated_data['publish_id'] = validated_data.pop('publish')
  26. for key in validated_data:
  27. setattr(instance, key, validated_data[key])
  28. instance.save()
  29. # 先清空在放入
  30. # instance.authors.clear()
  31. # instance.authors.add(*authors)
  32. # 直接存
  33. instance.authors.set(authors)
  34. return instance

views.py

  1. class BookView(APIView):
  2. def post(self, request):
  3. ser = BookSerializer(data=request.data)
  4. if ser.is_valid():
  5. ser.save()
  6. return Response(ser.data)
  7. else:
  8. return Response(ser.errors)
  9. class BookDetail(APIView):
  10. def put(self, request, pk):
  11. book = Book.objects.filter(pk=pk).first()
  12. ser = BookSerializer(instance=book, data=request.data)
  13. if ser.is_valid():
  14. ser.save()
  15. return Response(ser.data)
  16. else:
  17. return Response(ser.errors)

urls.py

  1. urlpatterns = [
  2. path('books/', views.BookView.as_view()),
  3. path('books/<int:pk>/', views.BookDetail.as_view()),
  4. ]

注:多表反序列化校验 --> 跟之前一样 

九、ModelSerializer使用

之前写的序列化类,继承了serializers.Serializer,跟表没有必然联系
ModelSerializer跟表一一对应,以后基本需要重写create和update

serializer.py

  1. ### 继承ModelSerializer --->少写代码
  2. class BookSerializer(serializers.ModelSerializer):
  3. # name = serializers.CharField(max_length=18,min_length=3) # 公共的
  4. # price = serializers.CharField() # 公共的
  5. # publish = serializers.IntegerField(write_only=True) # 只用来做反序列化
  6. # authors = serializers.ListField(write_only=True) # 只用来做反序列化
  7. # 上述操作,通过 Meta实现了
  8. # 扩写的字段,也要在fields注册
  9. # 方式二:定制字段
  10. # publish_detail = serializers.SerializerMethodField(read_only=True) # 只用来做序列化
  11. # author_list = serializers.SerializerMethodField(read_only=True) # 只用来做序列化
  12. # def get_publish_detail(self, obj):
  13. # return {'name': obj.publish.name, 'city': obj.publish.city}
  14. # def get_author_list(self, obj):
  15. # l = []
  16. # for author in obj.authors.all():
  17. # l.append({'name': author.name, 'age': author.age})
  18. # return l
  19. # 方式二:定制字段方式一
  20. # publish_detail = serializers.DictField(read_only=True)
  21. # author_list = serializers.ListField(read_only=True)
  22. class Meta:
  23. model = Book # 写了这两句,会把表模型中Book,所有字段映射过来
  24. # fields='__all__'
  25. fields = ['name', 'price', 'publish', 'authors', 'publish_detail', 'author_list']
  26. extra_kwargs = { # 给某个或某几个字段设置字段属性
  27. 'name': {'max_length': 18, 'min_length': 3},
  28. 'publish': {'write_only': True},
  29. 'authors': {'write_only': True},
  30. 'publish_detail': {'read_only': True},
  31. 'author_list': {'read_only': True},
  32. }
  33. # 一般不需要写create和update了---> ModelSerializer帮我们实现了
  34. # 局部钩子和全局钩子,该怎么写还怎么写
  35. # def validate_name(self,name):
  36. # pass

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号