一、Django自带的序列化组件 ==》对象序列化成json格式的字符串
from django.core import serializers
from django.core import serializers def test(request): book_list = Book.objects.all() ret = serializers.serialize("json", book_list) return HttpResponse(ret)
二、rest_framework序列化之Serializer
下面用一个例题来说明序列化组件的具体使用
models部分
1 from django.db import models 2 3 # Create your models here. 4 5 6 class Book(models.Model): 7 title=models.CharField(max_length=32) 8 price=models.IntegerField() 9 pub_date=models.DateField() 10 publish=models.ForeignKey("Publish") 11 authors=models.ManyToManyField("Author") 12 def __str__(self): 13 return self.title 14 15 class Publish(models.Model): 16 name=models.CharField(max_length=32) 17 email=models.EmailField() 18 def __str__(self): 19 return self.name 20 21 class Author(models.Model): 22 name=models.CharField(max_length=32) 23 age=models.IntegerField() 24 def __str__(self): 25 return self.name
views部分
1 from rest_framework.views import APIView 2 from rest_framework.response import Response 3 from .models import * 4 from django.shortcuts import HttpResponse 5 from django.core import serializers 6 7 8 from rest_framework import serializers 9 10 class BookSerializers(serializers.Serializer): ===》这里的Serializer是大写开头 11 title=serializers.CharField(max_length=32) 12 price=serializers.IntegerField() 13 pub_date=serializers.DateField() 14 publish=serializers.CharField(source="publish.name") 15 #authors=serializers.CharField(source="authors.all") 16 authors=serializers.SerializerMethodField() ==》这里用这个下面需要跟上get + 字段 17 def get_authors(self,obj): 18 temp=[] 19 for author in obj.authors.all(): 20 temp.append(author.name) 21 return temp 22 #此处可以继续用author的Serializers, 23 # def get_authors(self,obj): 24 # ret=obj.authors.all() 25 # ss=AuthorSerializer(ret,many=True) 26 # return ss.data 27 28 class BookViewSet(APIView): 29 30 def get(self,request,*args,**kwargs): 31 book_list=Book.objects.all() 32 # 序列化方式1: 33 # from django.forms.models import model_to_dict 34 # import json 35 # data=[] 36 # for obj in book_list: 37 # data.append(model_to_dict(obj)) 38 # print(data) 39 # return HttpResponse("ok") 40 41 # 序列化方式2: 42 # data=serializers.serialize("json",book_list) 43 # return HttpResponse(data) 44 45 # 序列化方式3: 46 bs=BookSerializers(book_list,many=True) #many=True代表有多条数据,如果只有一条数据,many=False 47 return Response(bs.data) 48 # 序列化方式4: 49 # ret=models.Book.objects.all().values('nid','title') 50 # dd=list(ret) 51 # return HttpResponse(json.dumps(dd))
注意:
source 如果是字段,会显示字段,如果是方法,会执行方法,不用加括号(authors=serializers.CharField(source='authors.all'))
如在模型中定义一个方法,直接可以在在source指定执行
二、rest_framework序列化之ModelSerializer
1 class BookSerializers(serializers.ModelSerializer): 2 class Meta: 3 model = models.Book 4 # fields = "__all__" 5 fields=['nid','title','authors','publish'] 6 # exclude=('nid',) #不能跟fields同时用 7 # depth = 1 #深度控制,写 几 往里拿几层,层数越多,响应越慢,官方建议0--10之间,个人建议最多3层 8 publish=serializers.SerializerMethodField() 9 def get_publish(self,obj): 10 return obj.publish.name 11 authors=serializers.SerializerMethodField() 12 def get_authors(self,obj): 13 ret=obj.authors.all() 14 ss=AuthorSerializer(ret,many=True) 15 return ss.data
三、序列化组件之请求数据校验和保存功能
1 class BookSerializers(serializers.ModelSerializer): 2 class Meta: 3 model=Book 4 fields="__all__" 5 6 #———————— 7 class BookView(APIView): 8 9 def post(self, request): 10 11 # 添加一条数据 12 print(request.data) 13 14 bs=BookSerializers(data=request.data) 15 if bs.is_valid(): 16 bs.save() # 生成记录 17 return Response(bs.data) 18 else: 19 20 return Response(bs.errors)
通过源码查看留的校验字段的钩子函数:
1 #is_valid---->self.run_validation-(执行Serializer的run_validation)-->self.to_internal_value(data)---(执行Serializer的run_validation:485行) 2 def validate_title(self, value): 3 from rest_framework import exceptions 4 raise exceptions.ValidationError('看你不顺眼') 5 return value 6 7 #全局 8 def validate(self, attrs): 9 from rest_framework import exceptions 10 if attrs.get('title')== attrs.get('title2'): 11 return attrs 12 else: 13 raise exceptions.ValidationError('不想等啊')
序列化组件源码分析
序列化组件,先调用__new__方法,如果many=True,生成ListSerializer对象,如果为False,生成Serializer对象 序列化对象.data方法--调用父类data方法---调用对象自己的to_representation(自定义的序列化类无此方法,去父类找) Aerializer类里有to_representation方法,for循环执行attribute = field.get_attribute(instance) 再去Field类里去找get_attribute方法,self.source_attrs就是被切分的source,然后执行get_attribute方法,source_attrs 当参数传过去,判断是方法就加括号执行,是属性就把值取出来