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

posted @ 2020-12-13 15:43  盲仔不瞎忙  阅读(423)  评论(0编辑  收藏  举报