序列化组件
一 Django自带序列化组件
from django.core import serializers def test(request): books = Book.objects.all() #进行序列化 res = serializers.serialize("json", books) return HttpResponse(res)
二 restframework序列化之Serializer类
在Models创建如下模型:
class Book(models.Model): nid = models.AutoField(primary_key=True) name = models.CharField(max_length=32) price = models.DecimalField(max_digits=5, decimal_places=2) publish_date = models.DateField() publish = models.ForeignKey(to='Publish',to_field='nid',on_delete=models.CASCADE) authors=models.ManyToManyField(to='Author') class Author(models.Model): nid = models.AutoField(primary_key=True) name = models.CharField(max_length=32) age = models.IntegerField() author_detail = models.OneToOneField(to='AuthorDatail',to_field='nid',unique=True,on_delete=models.CASCADE) class AuthorDatail(models.Model): nid = models.AutoField(primary_key=True) telephone = models.BigIntegerField() birthday = models.DateField() addr = models.CharField(max_length=64) class Publish(models.Model): nid = models.AutoField(primary_key=True) name = models.CharField(max_length=32) city = models.CharField(max_length=32) email = models.EmailField()
Views视图部分:
from rest_framework.views import APIView from rest_framework.response import Response from app01.models import * from django.shortcuts import HttpResponse from django.core import serializers
class BookSerializers(serializers.Serializer):
#继承Serializer类 name=serializers.CharField(max_length=32) price=serializers.IntegerField() pub_date=serializers.DateField() publish=serializers.CharField(source="publish.name") #authors=serializers.CharField(source="authors.all") authors=serializers.SerializerMethodField()
#SerializerMethodField方法 get_字段名 obj为每个传入的序列化的对象 def get_authors(self,obj): temp=[] for author in obj.authors.all(): temp.append(author.name) return temp #此处可以继续用author的Serializers, # def get_authors(self,obj): # ret=obj.authors.all() # ss=AuthorSerializer(ret,many=True) # return ss.data
class BookViewSet(APIView): def get(self,request,*args,**kwargs): book_list=Book.objects.all() # 序列化方式1: # from django.forms.models import model_to_dict # import json # data=[] # for obj in book_list: # data.append(model_to_dict(obj)) # print(data) # return HttpResponse("ok") # 序列化方式2: # data=serializers.serialize("json",book_list) # return HttpResponse(data) # 序列化方式3: res=BookSerializers(book_list,many=True) #many=True代表有多条数据,如果只有一条数据,many=False return Response(res.data)
总结:可以通过source指定字段,有外键关联的可以在source中通过点号查询指定关联表的某个字段名,如果没有指定source那么字段名必须和model中要序列化的类中字段名一样
三 restframework序列化之ModelSerializer类
class AuthorSerializers(serializers.ModelSerializer):
class Meta:
model=Author
fields='__all__'
class BookSerializers(serializers.ModelSerializer): class Meta:
#指定要序列化的类 model = Book # fields = "__all__" #序列化全部字段 fields=['nid','title','authors','publish'] #指定字段进行序列化 # exclude=('nid',) #除了……字段 不能跟fields同时用 # depth = 1 #深度控制,写几就会往里查询几层,层数越多,查询越慢,因为跨表查询太多 不建议使用 publish=serializers.SerializerMethodField() def get_publish(self,obj): return obj.publish.name authors=serializers.SerializerMethodField() def get_authors(self,obj): author_list=obj.authors.all() res=AuthorSerializer(author_list,many=True) return res.data
序列化组件源码相关:
序列化组件的实例化: 先调用父类BaseSerializer的__new__方法,如果many=True,生成ListSerializer对象,如果为False,生成Serializer对象 序列化对象.data方法: --调用父类Serializer的data方法---调用BaseSerializer的data方法---调用Serializer的to_representation方法,for循环执行 attribute =field.get_attribute(instance) 再去Field类里去找get_attribute方法,self.source_attrs就是被 ‘ . ’ 切分的source,然后执行get_attribute方法,判断是方法就加括号执行,是属性就把值取出来
三 数据校验和保存功能
数据的校验和新增:(必须继承ModelSerializer类)
urls:
urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^book/$', views.Book.as_view()), url(r'^book/(?P<pk>\d+)', views.BookDetail.as_view()), ]
class BookSerializers(serializers.ModelSerializer): class Meta: model=Book fields="__all__"
# 局部钩子 (validate_字段名)
def validate_name(self,value):
#拿到值,就可以进行判断了
#如果通过,把value值返回,
#如果不通过,抛 ValidationError 异常
pass
# 全局钩子
def validate(self,value):
#取出数据,进行判断
#如果通过,把value值返回,
#如果不通过,抛 ValidationError 异常
pass
class BookView(APIView): def post(self, request): # 添加一条数据 print(request.data) res=BookSerializers(data=request.data) # 开始进行校验 if res.is_valid(): res.save() # 生成记录 return Response(res.data) else:
# 错误信息 return Response(res.errors)
错误信息显示中文,类比Django中的forms组件:error_messages={'required': '该字段必填'}
源码查看校验流程:
is_valid() | v Serializer类下的run_validation() 函数 | v to_internal_value() 函数 获取局部校验函数 validate_method = getattr(self, 'validate_' + field.field_name, None) 先进行本身字段的校验 validated_value = field.run_validation(primitive_value) 再进行局部校验 validated_value = validate_method(validated_value) | v 回到Serializer类下的run_validation() 函数 进行全局校验 value = self.validate(value)
数据的校验和更新:
class BookDetail(APIView): def put(self,request,pk): book_obj=models.Book.objects.filter(pk=pk).first()
# 校验数据并更新 传入前台数据以及要更新的对象 res=BookSerializers(data=request.data,instance=book_obj) if res.is_valid(): res.save() return Response(res.data) else: return Response(res.errors)