zoukankan      html  css  js  c++  java
  • 二、drf序列化器

    drf序列化器

    一、序列化组件介绍

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

    二、Serializer简单使用

    • 步骤

      1. 写一个序列化的类,继承Serializer
      2. 在类中写要序列化的字段,想序列化哪个字段,就在类中写哪个字段
      3. 在视图类中使用,导入序列化类把要序列化的对象传入, 得到序列化对象
      4. 可以通过'序列化类的对象.data'获取序列化后的字典
      5. 把字典返回. 提示: 如果不使用rest_framework提供的Response,就得使用JsonResponse
      
    • 代码

      # models.py
      class Book(models.Model):
          name = models.CharField(max_length=32, verbose_name='书名')
          price = models.CharField(max_length=64, verbose_name='价格')
          author = models.CharField(max_length=64, verbose_name='作者')
          publish = models.CharField(max_length=64, verbose_name='出版社')
      
      
      # 自建一个py文件
      # ser.py
      class BookSerializer(serializers.Serializer):
          # id=serializers.CharField()
          name = serializers.CharField()
          # price=serializers.DecimalField()
          price = serializers.CharField()
          author = serializers.CharField()
          publish = serializers.CharField()
      
      
      # views.py
      class BookView(APIView):
          def get(self, request, pk):
              book = Book.objects.filter(id=pk).first()
              # 将从数据库中获取的book对象使用刚刚自定义的序列化类BookSerializer将book进行序列化
              book_ser = BookSerializer(book)  # 调用类的__init__
              # book_ser.data   # 序列化对象.data就是序列化后的字典
              return Response(book_ser.data)
      
      
      # urls.py
      re_path('books/(?P<pk>d+)', views.BookView.as_view()) 
      

    三、序列化类的字段类型

    1. 常用字段类型

    字段 字段构造方法
    BooleanField BooleanField()
    NullBooleanField NullBooleanField()
    CharField CharField(max_length=None, min_length=None, allow_blank=False, trim_whitespace=True)
    EmailField EmailField(max_length=None, min_length=None, allow_blank=False)
    RegexField RegexField(regex, max_length=None, min_length=None, allow_blank=False)
    SlugField SlugField(maxlength=50, min_length=None, allow_blank=False) 正则字段,验证正则模式 [a-zA-Z0-9-]+
    URLField URLField(max_length=200, min_length=None, allow_blank=False)
    UUIDField UUIDField(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"
    IPAddressField IPAddressField(protocol=’both’, unpack_ipv4=False, **options)
    IntegerField IntegerField(max_value=None, min_value=None)
    FloatField FloatField(max_value=None, min_value=None)
    DecimalField DecimalField(max_digits, decimal_places, coerce_to_string=None, max_value=None, min_value=None) max_digits: 最多位数 decimal_palces: 小数点位置
    DateTimeField DateTimeField(format=api_settings.DATETIME_FORMAT, input_formats=None)
    DateField DateField(format=api_settings.DATE_FORMAT, input_formats=None)
    TimeField TimeField(format=api_settings.TIME_FORMAT, input_formats=None)
    DurationField DurationField()
    ChoiceField ChoiceField(choices) choices与Django的用法相同
    MultipleChoiceField MultipleChoiceField(choices)
    FileField FileField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)
    ImageField ImageField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)
    ListField ListField(child=, min_length=None, max_length=None)
    DictField DictField(child=)

    2. 选项参数

    参数名称 作用
    max_length 最大长度
    min_lenght 最小长度
    allow_blank 是否允许为空
    trim_whitespace 是否截断空白字符
    max_value 最小值
    min_value 最大值

    3. 通用参数

    参数名称 说明
    read_only 表明该字段仅用于序列化输出,默认False
    write_only 表明该字段仅用于反序列化输入,默认False
    required 表明该字段在反序列化时必须输入,默认True
    default 反序列化时使用的默认值
    allow_null 表明该字段是否允许传入None,默认False
    validators 该字段使用的验证器
    error_messages 包含错误编号与错误信息的字典
    label 用于HTML展示API页面时,显示的字段名称
    help_text 用于HTML展示API页面时,显示的字段帮助提示信息

    四、序列化组件修改数据

    • 步骤

      1 写一个序列化的类,继承Serializer
      2 在类中写要反序列化的字段,想反序列化哪个字段,就在类中写哪个字段,字段的属性(max_lenth......)
      	max_length	最大长度
          min_lenght	最小长度
          allow_blank	是否允许为空
          trim_whitespace	是否截断空白字符
          max_value	最小值
          min_value	最大值
      3 在视图类中使用,导入--》实例化得到序列化类的对象,把要要修改的对象传入,修改的数据传入
      	boo_ser=BookSerializer(book,request.data)
          boo_ser=BookSerializer(instance=book,data=request.data)
      4 数据校验 if boo_ser.is_valid()
      5 如果校验通过,就保存
      	boo_ser.save()  # 注意不是book.save()
      6 如果不通过,逻辑自己写
      
      
      7 如果字段的校验规则不够,可以写钩子函数(局部和全局)
      		# 局部钩子
      	    def validate_price(self, data):   # validate_字段名  接收一个参数
                  #如果价格小于10,就校验不通过
                  # print(type(data))
                  # print(data)
                  if float(data)>10:
                      return data
                  else:
                      #校验失败,抛异常
                      raise ValidationError('价格太低')
               # 全局钩子
              	def validate(self, validate_data):   # 全局钩子
                      print(validate_data)
                      author=validate_data.get('author')
                      publish=validate_data.get('publish')
                      if author == publish:
                          raise ValidationError('作者名字跟出版社一样')
                      else:
                          return validate_data
      8 可以使用字段的author=serializers.CharField(validators=[check_author]) ,来校验
      	-写一个函数
          	def check_author(data):
                  if data.startswith('sb'):
                      raise ValidationError('作者名字不能以sb开头')
                  else:
                      return data
           -配置:validators=[check_author]
      
    • 代码

      # models.py
      class Book(models.Model):
          id = models.AutoField(primary_key=True)
          name = models.CharField(max_length=32)
          price = models.DecimalField(max_digits=5, decimal_places=2)
          author = models.CharField(max_length=32)
          publish = models.CharField(max_length=32)
      
      
      # ser.py
      # from rest_framework.serializers import Serializer  # Serializer就是一个序列化类
      from rest_framework import serializers
      from rest_framework.exceptions import ValidationError
      
      
      def check_author(data):
          if data.startswith('sb'):
              raise ValidationError('作者名字不能以sb开头')
          else:
              return data
      
      
      class BookSerializer(serializers.Serializer):
          # id=serializers.CharField()
          name = serializers.CharField(max_length=16, min_length=4)
          # price=serializers.DecimalField()
          price = serializers.CharField()
          author = serializers.CharField(validators=[check_author])  # validators=[] 列表中写函数内存地址
          publish = serializers.CharField()
      
          def validate_price(self, data):  # validate_字段名  接收一个参数
              # 如果价格小于10,就校验不通过
              # print(type(data))
              # print(data)
              if float(data) > 10:
                  return data
              else:
                  # 校验失败,抛异常
                  raise ValidationError('价格太低')
      
          def validate(self, validate_data):  # 全局钩子
              print(validate_data)
              author = validate_data.get('author')
              publish = validate_data.get('publish')
              if author == publish:
                  raise ValidationError('作者名字跟出版社一样')
              else:
                  return validate_data
      
          def update(self, instance, validated_data):
              # instance是book这个对象
              # validated_data是校验后的数据
              instance.name = validated_data.get('name')
              instance.price = validated_data.get('price')
              instance.author = validated_data.get('author')
              instance.publish = validated_data.get('publish')
              instance.save()  # book.save()   django 的orm提供的
              return instance
      
      
      # views.py
      class BookView(APIView):
          def get(self, request, pk):
              book = Book.objects.filter(id=pk).first()
              # 用一个类,毫无疑问,一定要实例化
              # 要序列化谁,就把谁传过来
              book_ser = BookSerializer(book)  # 调用类的__init__
              # book_ser.data   序列化对象.data就是序列化后的字典
              return Response(book_ser.data)
              # return JsonResponse(book_ser.data)
      
          def put(self, request, pk):
              response_msg = {'status': 100, 'msg': '成功'}
              # 找到这个对象
              book = Book.objects.filter(id=pk).first()
              # 得到一个序列化类的对象
              # boo_ser=BookSerializer(book,request.data)
              boo_ser = BookSerializer(instance=book, data=request.data)
      
              # 要数据验证(回想form表单的验证)
              if boo_ser.is_valid():  # 返回True表示验证通过
                  boo_ser.save()  # 报错
                  response_msg['data'] = boo_ser.data
              else:
                  response_msg['status'] = 101
                  response_msg['msg'] = '数据校验失败'
                  response_msg['data'] = boo_ser.errors
      
              return Response(response_msg)
      
      
      # urls.py
      re_path('books/(?P<pk>d+)', views.BookView.as_view()),
      

    五、read_only和write_only

    • 常用
      • read_only:表明该字段仅用于序列化输出,默认False,如果设置成True,postman中可以看到该字段,修改时,不需要传该字段
      • write_only:表明该字段仅用于反序列化输入,默认False,如果设置成True,postman中看不到该字段,修改时,该字段需要传
    • 了解
      • required 表明该字段在反序列化时必须输入,默认True
      • default 反序列化时使用的默认值
      • allow_null 表明该字段是否允许传入None,默认False
      • validators 该字段使用的验证器
      • error_messages 包含错误编号与错误信息的字典

    六、查询所有

    class BooksView(APIView):
        def get(self, request):
            response_msg = {'status': 100, 'msg': '成功'}
            books = Book.objects.all()
            book_ser = BookSerializer(books, many=True)  # 序列化多条,如果序列化一条,不需要写
            response_msg['data'] = book_ser.data
            return Response(response_msg)
    
    # urls.py
    path('books/', views.BooksView.as_view())
    

    七、新增数据

    # views.py
    class BooksView(APIView):
        # 新增
        def post(self,request):
            response_msg = {'status': 100, 'msg': '成功'}
            #修改才有instance,新增没有instance,只有data
            book_ser = BookSerializer(data=request.data)
            # book_ser = BookSerializer(request.data)  # 这个按位置传request.data会给instance,就报错了
            # 校验字段
            if book_ser.is_valid():
                book_ser.save()
                response_msg['data']=book_ser.data
            else:
                response_msg['status']=102
                response_msg['msg']='数据校验失败'
                response_msg['data']=book_ser.errors
            return Response(response_msg)
        
    #ser.py 序列化类重写create方法
        def create(self, validated_data):
            instance=Book.objects.create(**validated_data)
            return instance
        
    # urls.py
    path('books/', views.BooksView.as_view())
    

    八、删除一个数据

    # views.py
    class BookView(APIView):
        def delete(self,request,pk):
            ret=Book.objects.filter(pk=pk).delete()
            return Response({'status':100,'msg':'删除成功'})
        
    # urls.py
    re_path('books/(?P<pk>d+)', views.BookView.as_view()),
    

    九、模型类序列化器

    class BookModelSerializer(serializers.ModelSerializer):
        class Meta:
            model = models.Book # 对应models.Book中所有的字段
            fields = '__all__' # 序列化所有的字段
            fields = ("name",'price','author',) # 只序列化fields中指定的字段
            exclude = ('id','name',) # 只序列化exclude中没有的字段
            read_only_fields = ('id','name') # 需要配合fields = '__all__'一起来使用,反序列化时,不需要填写read_only_fields中的字段
            write_only_fields = ('name','price') # 已弃用,可以使用extra_kwargs代替
            extra_kwargs = { # 需要配合fields = '__all__'一起来使用,类似于:price = serializers.CharField(write_only=True)
                 'price':{'write_only':True},
             }
    
    # 其他使用一模一样
    # 不需要重写create和updata方法了
    

    十、源码分析

    1. many=True

    # 序列化多条,需要传many=True
    
    book_ser=BookModelSerializer(books,many=True)
    book_one_ser=BookModelSerializer(book)
    print(type(book_ser))
    # <class 'rest_framework.serializers.ListSerializer'>
    print(type(book_one_ser))
    # <class 'app01.ser.BookModelSerializer'>
    
    # 对象的生成--》先调用类的__new__方法,生成空对象
    # 对象=类名(name=lqz),触发类的__init__()
    # 类的__new__方法控制对象的生成
    
    
    def __new__(cls, *args, **kwargs):
        if kwargs.pop('many', False):
            return cls.many_init(*args, **kwargs)
        # 没有传many=True,走下面,正常的对象实例化
        return super().__new__(cls, *args, **kwargs)
    

    2.Serializer高级用法

    2.1 source参数

    # 1. 可以改字段名字  
        xxx = serializers.CharField(source='title')
    # 2. 可以.跨表
        publish = serializers.CharField(source='publish.email')
    # 3. 可以执行方法
        pub_date= serializers.CharField(source='test')  # 注: test是Book表模型中的方法
    

    2.2 SerializerMethodField

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

    十一、补充

    1. is_valid的另一种用法

    is_valid()方法还可以在验证失败时抛出异常serializers.ValidationError,可以通过传递raise_exception = True参数开启,REST框架接收到此异常,会向前端返回HTTP 400错误的请求响应。

    # Return a 400 response if the data was invalid.
    serializer.is_valid(raise_exception=True)
    

    2. 自己封装Response对象

    class MyResponse():
        def __init__(self):
            self.status=100
            self.msg='成功'
        @property
        def get_dict(self):
            return self.__dict__
    
    if __name__ == '__main__':
        res=MyResponse()
        res.status=101
        res.msg='查询失败'
        # res.data={'name':'lqz'}
        print(res.get_dict)
    
  • 相关阅读:
    PAT A1094 The Largest Generation (25 分)——树的bfs遍历
    PAT A1055 The World's Richest (25 分)——排序
    PAT A1052 Linked List Sorting (25 分)——链表,排序
    PAT A1076 Forwards on Weibo (30 分)——图的bfs
    辅导员
    辅导员面试
    C程序设计
    Excel VBA 基本概念
    Excel函数
    导入excel表的数据到数据库ssh
  • 原文地址:https://www.cnblogs.com/borntodie/p/14330723.html
Copyright © 2011-2022 走看看