目录
    • **serializermethodfield( ) **
    • 六、源码分析many=true

      一、序列化器-serializer

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

      二、序列化器的使用

      序列化器的使用分为两个阶段:

      • 在客户端请求时,使用序列化器可以完成对数据的反序列化。
      • 在服务器响应时,使用序列化器可以完成对数据的序列化。

      简单使用

      1、创建一个表模型

      from django.db import models
      
      class 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 serializers
      
      class 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 apiview
      from rest_framework.request import request
      from app01.models import books
      from app01.ser import booksserializer
      
      class 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.data
              return response(response_msg)
          
       # urls.py
      re_path(r'^book/(?p<pk>\d+)/', views.bookview.as_view()),
      
      

      7、如果要被序列化的是包含多条数据的查询集queryset,可以通过添加many=true参数

      from rest_framework.views import apiview
      from rest_framework.response import response
      from app01.models import books
      from app01.ser import booksserializer
      
      
      class 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.data
              return response(response_msg)
      
      # urls.py
      re_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.py
      class 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.py
      class 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 serializers
      
      class 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=request.data),调用is_valid()方法校验,校验成功返回true,失败返回false。

      失败,可以通过序列化器对象的errors获取错误信息(字典)

      成功,可以公共序列化对象的validated_data属性获取数据。

      校验方法有:局部钩子,全局钩子,validators,和序列化类型和字段属性也是

      字段属性

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

      局部钩子

      在序列化器类中创建局部钩子:validate_字段名,并且接收一个参数

      # ser.py
      class 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 data
              else:
                  # 校验失败就抛异常
                  raise validationerror('价格太低')
      

      全局钩子

      全局钩子:validate( ), 接收一个参数,

      同时对多个字段进行比较验证

      # ser.py
      class 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_data
          else:
              raise validationerror('书名和出版社不能一致')
      

      validators

      使用字段的validators=[func],来校验

      # ser.py
      # 校验函数
      def check_price(data):
          if float(data) > 10:
              return data
          else:
              raise validationerror('价格太低')
      
      class booksserializer(serializers.serializer):
          title = serializers.charfield()
          publish = serializers.charfield()
          price = serializers.charfield(validators=[check_price]) # 配置

      四、序列化器操作数据

      查询所有

      # views.py
      class 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.data
              return response(response_msg)
          
      # urls.py
      path('books/', views.booksview.as_view()),
      

      查询单条

      # views.py
      class 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.data
              return response(response_msg)
          
      # urls.py
      re_path(r'^book/(?p<pk>\d+)/', views.bookview.as_view()),
      

      新增数据

      新增数据需要在序列化器中重写create( ) 方法:

      注意没有传递instance实例,则调用save()方法的时候,create()被调用,相反,如果传递了instance实例,调用save()方法的时候,update()被调用。

      # views.py
      class bookview(apiview):
          def post(self, request):
              # 响应信息
              response_msg = {'status': 201, 'message': '增加成功'}
              # 修改才有instance,新增没有instance,只有data
              book_ser = booksserializer(data=request.data)
      
              # 校验字段
              if book_ser.is_valid():
                  book_ser.save()  # 需要在序列化器中重写create()方法
                  # 保存成功把原数据返回
                  response_msg['data'] = book_ser.data
              else:
                  response_msg['status'] = 202
                  response_msg['message'] = '数据校验失败'
                  response_msg['data'] = book_ser.error_messages
              return response(response_msg)
          
          
      # ser.py
      class booksserializer(serializers.serializer):
          title = serializers.charfield()
          publish = serializers.charfield()
          price = serializers.decimalfield(max_digits=5, decimal_places=2)
      
          # 重写create
          def create(self, validated_data):   # validated_data——>传入的新增数据
              instance = books.objects.create(**validated_data)
              # instance——> 新增的字段对象,需要返回
              return instance
             
      # urls.py
      path('book/', views.bookview.as_view()),

      修改数据

      修改数据需要在序列化器中重写update( ) 方法:

      # views.py
      class 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=request.data)
      
              # 校验数据
              if book_ser.is_valid():
                  book_ser.save()     # 需要在序列化器中重写update()方法
                  response_msg['data'] = book_ser.data
              else:
                  response_msg['status'] = 202
                  response_msg['message'] = '数据校验失败'
                  response_msg['data'] = book_ser.error_messages
              return response(response_msg)
          
      # urls.py
      re_path('book/(?p<pk>\d+)', views.bookview.as_view()),

      删除数据

      # views.py
      class booksview(apiview):
          def delete(self, request, pk):
          # 响应信息
          response_msg = {'status': 200, 'message': '删除成功'}
          # 删除数据
          books.objects.filter(pk=pk).delete()
          return response(response_msg)
          
      # urls.py
      re_path('book/(?p<pk>\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))
      #<class 'rest_framework.serializers.listserializer'>
      
      print(type(book_one_ser))
      #<class 'app01.ser.bookmodelserializer'>
      
      # 对象的生成-->先调用类的__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内容请搜索www.887551.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持www.887551.com!