drf序列化器serializer的具体使用

目录

  • 一、序列化器-serializer
  • 二、序列化器的使用
    • 简单使用
  • 高级使用
    • source
    • **SerializerMethodField( ) **
    • 通用参数
  • 三、反序列化数据校验
    • 字段属性
    • 局部钩子
    • 全局钩子
    • validators
  • 四、序列化器操作数据
    • 查询所有
    • 查询单条
    • 新增数据
    • 修改数据
    • 删除数据
  • 五、模型类序列化器
    • 六、源码分析many=True

      一、序列化器-serializer
      • 序列化,序列化器会把模型对象转成字典,经过response以后变成JSON字符串
      • 反序列化:把客户端发送过来的数据,经过request以后变成字典,序列化器可以把字典转成模型
      • 反序列化:完成数据校验功能

      二、序列化器的使用
      序列化器的使用分为两个阶段:
      • 在客户端请求时,使用序列化器可以完成对数据的反序列化。
      • 在服务器响应时,使用序列化器可以完成对数据的序列化。

      简单使用

      1、创建一个表模型
      from django.db import modelsclass Books(models.Model):title = models.CharField(verbose_name='书名', max_length=32)publish = models.CharField(verbose_name='出版社', max_length=32)price = models.DecimalField(verbose_name='价格', max_digits=5, decimal_places=2)

      2、新建一个py文件,写一个序列化的类,继承Serializer
      3、在类中写要序列化的字段,想序列化那个字段,就在类中写那个字段
      from rest_framework import serializersclass BooksSerializer(serializers.Serializer):title = serializers.CharField()publish = serializers.CharField()price = serializers.DecimalField()

      4、在视图类中使用,导入——》实例化得到序列化对象,把要序列化的对象传入
      5、序列化的对象.data——》是一个字典
      6、把字典返回,如果不使用rest_framework提供的Response,就得使用JsonResponse
      from rest_framework.views import APIViewfrom rest_framework.request import Requestfrom app01.models import Booksfrom app01.ser import BooksSerializerclass BookView(APIView):def get(self, request, pk):# 响应信息response_msg = {'status': 200, 'message': '查询成功'}# 获取要序列化的对象book = Books.objects.filter(pk=pk).first()# 要序列化谁就把谁传到序列化类去book_ser = BooksSerializer(book)# book_ser.data————》序列化对象.data————》就是序列化后的字典# 将查询结果添加到响应信息内response_msg['data'] = book_ser.datareturn Response(response_msg) # urls.pyre_path(r'^book/(?P\d+)/', views.BookView.as_view()),

      7、如果要被序列化的是包含多条数据的查询集queryset,可以通过添加many=True参数
      from rest_framework.views import APIViewfrom rest_framework.response import Responsefrom app01.models import Booksfrom app01.ser import BooksSerializerclass BooksView(APIView):def get(self, request):# 响应信息response_msg = {'status': 200, 'message': '查询成功'}books = Books.objects.all()# 要序列化谁就把谁传到序列化类去book_ser = BooksSerializer(books, many=True)# book_ser.data————》序列化对象.data————》就是序列化后的字典# 将查询结果添加到响应信息内response_msg['data'] = book_ser.datareturn Response(response_msg)# urls.pyre_path(r'^books/', views.BookView.as_view()),


      高级使用

      source

      1、可以修改字段名字
      class BooksSerializer(serializers.Serializer):xxx = serializers.CharField(source='title')# 相当于——》xxx = Books.title# 响应{"status": 200,"message": "查询成功","data": {"xxx": "魔道祖师"————》响应的字段名被修改了}}

      2、可以跨表查询
      class BookSerializer(serializers.Serializer):publish_email = serializers.CharField(source='publish.email')# 相当于——》publish_email = Book.publish.email 连表查询publish表的email字段# 响应{"status": 200,"message": "查询成功","data": {"publish_email": "modao@163.com"}}

      3、可以执行方法
      # models.pyclass Book(models.Model):title = models.CharField(max_length=32)price = models.IntegerField()pub_date = models.DateTimeField()publish = models.ForeignKey("Publish", on_delete=models.CASCADE, null=True)authors = models.ManyToManyField("Author")def func(self):return '666666'# ser.pyclass BookSerializer(serializers.Serializer):msg = serializers.CharField(source='func')# msg = Book.func——》调用Book类中的func()方法的返回值# 响应{"status": 200,"message": "查询成功","data": {"msg": "666666"}}


      **SerializerMethodField( ) **

      它需要有一个配套的方法,方法名叫做get_字段名,返回值就是要显示的东西
      class BookSerializer(serializers.Serializer):authors = serializers.SerializerMethodField()def get_authors(self, instance):# instance ——》 Book对象authors = instance.authors.all()# 取出所有作者author_list = []for author in authors:author_list.append({'name': author.name, 'age': author.age})return author_list


      通用参数

      read_only:(只读)表明该字段仅用于序列化输出,默认False,如果设置成True,响应中可以看到该字段,修改时,不需要传该字段
      write_only:(只写)表明该字段仅用于反序列化输入,默认False,如果设置成True,响应中看不到该字段,修改时,该字段需要传
      from rest_framework import serializersclass BooksSerializer(serializers.Serializer):title = serializers.CharField(read_only = True)# 响应中能看到改字段,修改不需要传值publish = serializers.CharField(write_only = True) # 响应中看不到改字段,修改需要传值price = serializers.DecimalField()

      还有参数如下:
      • required表明该字段在反序列化时必须输入,默认True
      • default反序列化时使用的默认值
      • allow_null表明该字段是否允许传入None,默认False
      • validators该字段使用的验证器
      • error_messages 包含错误编号与错误信息的字典

      三、反序列化数据校验
      当使用序列化器对数据进行反序列化时,就需要对数据进行校验了,只有校验成功的数据才能被保存成模型类对象
      将要校验的数据传入序列化器中并实例化:obj = BooksSerializer(data=https://www.it610.com/article/request.data),调用is_valid()方法校验,校验成功返回True,失败返回False。
      失败,可以通过序列化器对象的errors获取错误信息(字典)
      成功,可以公共序列化对象的validated_data属性获取数据。
      校验方法有:局部钩子,全局钩子,validators,和序列化类型和字段属性也是

      字段属性
      • max_length最大长度
      • min_lenght最小长度
      • allow_blank是否允许为空
      • trim_whitespace 是否截断空白字符
      • max_value最小值
      • min_value最大值

      局部钩子

      在序列化器类中创建局部钩子:validate_字段名,并且接收一个参数
      # ser.pyclass BooksSerializer(serializers.Serializer):title = serializers.CharField()publish = serializers.CharField()price = serializers.DecimalField(max_digits=5, decimal_places=2)# 局部钩子对price字段校验def validate_price(self, data):if float(data) > 20:# 校验成功就通过return dataelse:# 校验失败就抛异常raise ValidationError('价格太低')


      全局钩子

      全局钩子:validate( ), 接收一个参数,
      同时对多个字段进行比较验证
      # ser.pyclass BooksSerializer(serializers.Serializer):title = serializers.CharField()publish = serializers.CharField()price = serializers.DecimalField(max_digits=5, decimal_places=2)def validate(self, validate_data):title = validate_data.get('title')publish = validate_data.get('publish')if not title == publish:return validate_dataelse:raise ValidationError('书名和出版社不能一致')


      validators

      使用字段的validators=[func],来校验
      # ser.py# 校验函数def check_price(data):if float(data) > 10:return dataelse:raise ValidationError('价格太低')class BooksSerializer(serializers.Serializer):title = serializers.CharField()publish = serializers.CharField()price = serializers.CharField(validators=[check_price]) # 配置


      四、序列化器操作数据

      查询所有

      # views.pyclass BooksView(APIView):def get(self, request):# 响应信息response_msg = {'status': 200, 'message': '查询成功'}# 获取所有数据books = Books.objects.all()# 把数据谁传到序列化器中book_ser = BooksSerializer(instance=books, many=True) # 序列化多条需要加 many=True# book_ser.data————》序列化对象.data————》就是序列化后的字典# 将查询结果添加到响应信息内response_msg['data'] = book_ser.datareturn Response(response_msg)# urls.pypath('books/', views.BooksView.as_view()),


      查询单条

      # views.pyclass BookView(APIView):def get(self, request, pk):# 响应信息response_msg = {'status': 200, 'message': '查询成功'}# 获取要序列化的对象book = Books.objects.filter(pk=pk).first()# 要序列化谁就把谁传到序列化器中book_ser = BooksSerializer(instance=book)# book_ser.data————》序列化对象.data————》就是序列化后的字典# 将查询结果添加到响应信息内response_msg['data'] = book_ser.datareturn Response(response_msg)# urls.pyre_path(r'^book/(?P\d+)/', views.BookView.as_view()),


      新增数据

      新增数据需要在序列化器中重写create( ) 方法:
      注意没有传递instance实例,则调用save()方法的时候,create()被调用,相反,如果传递了instance实例,调用save()方法的时候,update()被调用。
      # views.pyclass BookView(APIView):def post(self, request):# 响应信息response_msg = {'status': 201, 'message': '增加成功'}# 修改才有instance,新增没有instance,只有databook_ser = BooksSerializer(data=https://www.it610.com/article/request.data)# 校验字段if book_ser.is_valid():book_ser.save()# 需要在序列化器中重写create()方法# 保存成功把原数据返回response_msg['data'] = book_ser.dataelse:response_msg['status'] = 202response_msg['message'] = '数据校验失败'response_msg['data'] = book_ser.error_messagesreturn Response(response_msg)# ser.pyclass BooksSerializer(serializers.Serializer):title = serializers.CharField()publish = serializers.CharField()price = serializers.DecimalField(max_digits=5, decimal_places=2)# 重写createdef create(self, validated_data):# validated_data——>传入的新增数据instance = Books.objects.create(**validated_data)# instance——> 新增的字段对象,需要返回return instance# urls.pypath('book/', views.BookView.as_view()),


      修改数据

      修改数据需要在序列化器中重写update( ) 方法:
      # views.pyclass BookView(APIView):def put(self, request, pk):# 响应信息response_msg = {'status': 200, 'message': '修改成功'}# 获取需要修改的字段对象book = Books.objects.filter(pk=pk).first()# 将字段对象和修改数据添加到序列化器中book_ser = BooksSerializer(instance=book, data=https://www.it610.com/article/request.data)# 校验数据if book_ser.is_valid():book_ser.save()# 需要在序列化器中重写update()方法response_msg['data'] = book_ser.dataelse:response_msg['status'] = 202response_msg['message'] = '数据校验失败'response_msg['data'] = book_ser.error_messagesreturn Response(response_msg)# urls.pyre_path('book/(?P\d+)', views.BookView.as_view()),


      删除数据

      # views.pyclass BooksView(APIView):def delete(self, request, pk):# 响应信息response_msg = {'status': 200, 'message': '删除成功'}# 删除数据Books.objects.filter(pk=pk).delete()return Response(response_msg)# urls.pyre_path('book/(?P\d+)', views.BooksView.as_view()),


      五、模型类序列化器
      DRF提供了ModelSerializer模型类序列化器来帮助我们快速创建一个Serializer类。
      ModelSerializer与常规的Serializer相同,但是提供了:
      • 基于模型类自动生成一系列字段
      • 基于模型类自动为Serializer生成validators,比如unique_together
      • 包含默认的create( ) 和update( )。
      实例:
      class BookSerializer(serializers.ModelSerializer):class Meta:model = Book# 指明参照那个模型类fields = '__all__'# 为模型类的那些字段生成

      字段操作
      1、可以使用fields来明确字段,__all__表示包含所以字段,具体那些字段->fields = ('title','price')
      2、exclude表示排除那些字段,不能和fields一起写——>exclude = ('price',)
      3、额外参数extra_kwargs,给字段添加额外的参数
      class BookSerializer(serializers.ModelSerializer):class Meta:model = Book# 指明参照那个模型类fields = '__all__'# 为模型类的那些字段生成# 类似于title = serializers.CharField(read_only = True)extra_kwargs = {'title': {'read_only': True},}


      六、源码分析many=True
      当我们需要查询多条数据时就需要在实例化序列化器的时候传many=True
      book_ser = BooksSerializer(instance=books, many=True) # 查询多条book_one_ser = BooksSerializer(instance=book) # 查询单条print(type(book_ser))#print(type(book_one_ser))## 对象的生成-->先调用类的__new__方法,生成空对象,如果many=True,生成ListSerializer对象,反之生成Serializer对象# 类的__new__方法控制对象的生成def __new__(cls, *args, **kwargs):# 如果many=True,就会自动创建ListSerializer类if kwargs.pop('many', False):return cls.many_init(*args, **kwargs)return super().__new__(cls, *args, **kwargs)

      【drf序列化器serializer的具体使用】到此这篇关于drf序列化器serializer的具体使用的文章就介绍到这了,更多相关drf序列化器serializer内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

        推荐阅读