zoukankan      html  css  js  c++  java
  • Rest_Framework--Serializers类

    序列化
    由于queryset不能被json序列化,所以我们要对数据转换一下
    方式一:list强转
    data=list(Book.objects.all().values("title","price"))
    json.dumps(data,ensure_ascii=False) 可以解决页面上中文乱码的问题.
     
    方式二:拼凑格式
    booklist=Book.objects.all()
            temp=[]
            for book in booklist:
                temp.append({
                    "title":book.title,
                    "price":book.price
                    
                })
            return HttpResponse(json.dumps(temp))
     
    方式三:Django的序列化工具serializers
    以上三种的缺点: 尽管能把数据json序列化,但是不能json反序列化
     
    方式四:restframwork专门处理序列化的组件:serializers组件
     
    当我们用ORM查询出数据集时,默认存放在Django的QuerySet对象中,我们不能直接把QuerySet对象的数据返回给前端,在给前端前我们需要对数据进行解析,若我们自己实现,肯定是遍历、创建字典、把数据存到字典内、然后在json dump等,做这一系列冗余无聊的动作
    但当我们使用Serializer后,代码相比较来说就会很简洁
     
    Serializers类
    1.声明表
    首先,在models.py文件下创建一个模型:
    class Book(models.Model):
        name = models.CharField(max_length=11)
        price = models.IntegerField()
        
    class Publisher(models.Model):
      name = models.CharField(max_length=32)
    
    class Author(models.Model):
      name = models.CharField(max_length=32)      
     
    2.声明序列化规则
    声明序列化规则看起来与声明表单非常相似:
    # 序列化就是数据库把数据发给前端显示
    # 反序列化是从前端获取数据存到数据库
    class BookSerializer(serializers.Serializer):
        name = serializers.CharField(label='名字', max_length=11)  # label 标签
        price = serializers.IntegerField(label='价格', required=True)  # required= True表示一定要接收数据
    对于一对多字段这样设置:
    class Bookserializers(serializers.Serializer):
        name =serializers.CharField(max_length=32)
        price =serializers.IntegerField()
        publish=serializers.Charfield(source="publish.name") #这里可以指定显示的具体字段,如果不指定就显示主键值
     对于多对多字段你需要重新定义多对多字段:
    class Bookserializers(serializers.Serializer):
        name = serializers.CharField(max_length=32)
        price = serializers.IntegerField()
        pub_date = serializers.DateField()
        publish = serializers.CharField()#一对多
        authors = serializers.SerializerMethodField() #对多对
        def get_authors(self,obj): #函数名字必须为get_多对多字段形式,obj就是每个Book对象,源码中规定的
            temp=[]
            for author in obj.authors.all():
                temp.append(author.name) #把多对多的名字显示出来
            return temp
     
    3.序列化对象
    obj = Book.objects.all()
    ser = BookSerializer(obj, many=True)   # obj 是对象列表,里面有多个对象,所以这里就要添加many=True
    pprint.pprint(ser.data)  # python本机数据类型(字典,列表)
     
    4.接着为了完成序列化过程将数据渲染到json。
    from rest_framework.renderers import JSONRenderer
    json_data = JSONRenderer().render(ser.data)
    pprint.pprint(json_data)
     
    5.反序列化(serializers.py)
    如果是Django模型,然后想把验证后的数据保存到数据库。当我们需要创建或更新数据时,必须要在Serializer类中实现create、update方法,若不实现会报错。
    例如,Book是Django模型,下面代码为:
    class BookSerializer(serializers.Serializer):
        name = serializers.CharField(label='名字', max_length=11)
        price = serializers.IntegerField(label='价格', required=True)
    
        def create(self, validated_data):
            return Book.objects.create(**validated_data)
            
        def update(self, instance, validated_data):
            instance.name = validated_data.get('name', instance.name)
            instance.price = validated_data.get('price', instance.price)
            instance.save()  #调用instance.save()使数据保存至instance实例中
            return instance
     
    6.传参验证(views.py)
    在反序列化数据时,一定需要is_valid()在尝试访问经过验证的数据之前调用。
    保存数据至数据库,注意:
    需要在serializers.py中的create、update方法内调用instance.save()使数据先保存至instance实例中;
    其次需要在views.py中的create、update方法内调用serializer.save()保存至序列化对象内并落库;
    class TestView(APIView):
        def add_book(self, request):
            data = request.data
            ser1 = BookSerializer(data=data, many=True)
            if ser1.is_valid()   # 校验数据,如果 ser1.is_valid() 返回的是False,可以通过.errors属性来显示错误信息。
                ser1.save()     #保存至序列化对象内并落库
                return Response(ser1.data)
            else:
                return Response(ser1.errors)
        def update_book(self, request):
                data = request.data
                obj_price = data.pop('price')
                instance = Book.objects.get(price=obj_price)
                ser1 = BookSerializer(instance, data=data, partial=True) #其中partial参数设置为True,表示可以更新部分数据,否则不能正常更新。
                if ser1.is_valid():
                    ser1.save()   #保存至序列化对象内并落库
                    return Response(ser1.data)
                else:
                    return Response(ser1.errors)    
    还可以通过下面的方法显示无效数据的异常:
    ser1 = BookSerializer(data=data, many=True)
    ser1.is_valid(raise_exception=True)   # 校验数据,如果错误则自动返回错误信息
     
    字段级验证(serializers.py)
    要执行需要访问单个字段的时候的验证,例子如下:
    from rest_framework import serializers
    
    class BookSerializer(serializers.Serializer):
        '''主要是POST请求,来调用create'''
        name = serializers.CharField(label='名字', max_length=11)
        price = serializers.IntegerField(label='价格', required=True)
    
        def create(self, validated_data):
            return Book.objects.create(**validated_data)
    
        def validate_name(self, value):
            if len(value)>9:
                raise serializers.ValidationError("名字的长度不能大于9")
            return value
     
    对象级验证(serializers.py)
    要执行需要访问多个字段的时候的验证,例子如下:
    from rest_framework import serializers
    
    class BookSerializer(serializers.Serializer):
        '''主要是POST请求,来调用create'''
        name = serializers.CharField(label='名字', max_length=11)
        price = serializers.IntegerField(label='价格', required=True)
    
        def create(self, validated_data):
            return Book.objects.create(**validated_data)
    
        def validate(self, attrs):
            name = attrs['name']
            price = attrs['price']
            if name.isnumeric():
                raise serializers.ValidationError('名字不能有数字')
            if price > 250:
                raise serializers.ValidationError('价格不能太贵')
            return attrs

    其它参考文章:https://www.cnblogs.com/wang-kai-xuan/p/11247496.html

  • 相关阅读:
    什么是面向对象(OOP)
    Java虚拟机(JVM)你只要看这一篇就够了!
    ES6中新增的Object.assign()方法详解
    微信小程序_专题_脚本之家(小程序全部知识点)
    微信小程序 生命周期详解
    vue 阻止事件冒泡,捕获方法
    Java必备常见单词
    JS夸页面通信极简方案&纯前端实现文件下载
    vue keep-alive以及activated,deactivated生命周期的用法
    JVM实用参数 内存调优
  • 原文地址:https://www.cnblogs.com/absoluteli/p/14128816.html
Copyright © 2011-2022 走看看