序列化
由于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