序列化组件

一 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)
posted on 2018-12-11 15:48  叶杨森  阅读(159)  评论(0编辑  收藏  举报