序列化组件

Posted zkpython

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了序列化组件相关的知识,希望对你有一定的参考价值。

序列化组件

django自带的有序列化组件不过不可控不建议使用(了解)

技术图片
from django.core import serializers 

class Books(APIView):
    def get(self,request):
        response = code:100,msg:查询成功
        books = models.Book.objects.all()
        # 了解django自带的序列化组件
        ret= serializers.serialize("json",books)
        return HttpResponse(ret)
技术图片

 技术图片

使用drf的序列化组件

  自定义py文件里为了和view视图函数隔离开 自定义文件中写serializer组件

    1 新建一个序列化类继承Serializer   2  在类中写序列化的字段

      source=‘表中字段‘  自定义的字段不能和表中的字段名一样 

      source的值传给了默认形参instance 视图函数中的instance可以不写  

      source可以写跨表字段‘publish.name‘  之前跨表是book.publish.name 现在用source就可以省略book了 写成publish.name  

      source不但可以指定一个字段 还可以指定一个方法 

技术图片
#自定义的py文件中

from rest_framework import serializers    #序列化组件


class BookSerializer(serializers.Serializer):
# 指定source = ‘name‘ 表示序列化模型表中的name字段 重命名为name5(name5这个字段名 和source=’name‘指定的模型表中的name字段名不能一样)
    name5 = serializers.CharField(source=name)
    # write_only 序列化的时候,该字段前端不显示
    # read_only   反序列化的时候,该字段不传 前端传过来的时候可以不传参数或者字段
    price = serializers.CharField(write_only=True)

    #如果要取 出版社的city 之前跨表查询是 book.publish.city   现在 source = ‘publish.city‘ 不需要点击本身这张表的字段了
    #   source的值传给了默认形参instance
    publish = serializers.CharField(source=publish.name)  #出版社名字

    #source不但可以指定一个字段,还可以指定一个方法  自定义choices字段取值固定用法get_字段_display
    book_type = serializers.CharField(source=get_category_display,read_only=True)
技术图片

 

技术图片
#model.py模型表
class Book(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=8,decimal_places=2)
    category = models.IntegerField(choices=((0,文学类),(1,情感类)),default=1,null=True)
    publish = models.ForeignKey(to=Publish,to_field=nid,on_delete=models.CASCADE,null=True)
    authors = models.ManyToManyField(to=Author)

    def __str__(self):
        return self.name

    def test(self):
        return 方法
技术图片

 

   在视图中使用序列化的类

     实例化序列化的类产生对象,在产生对象的时候,传入需要序列化的对象(queryset)   

    对象.data    

     return Response(对象.data) 返回值用Response返回 

       如果序列化多条 many=True(也就是queryset对象,就需要写)  如果序列化一条(可以不写)instance是要序列化的对象

     

技术图片
from app01.app01serializer import BookSerializer    #自定义的py文件下的序列化组件
from rest_framework.response import Response    #返回用的

class Books(APIView):
    def get(self,request):
        response = code:100,msg:查询成功
        books = models.Book.objects.all()
       
        bookser = BookSerializer(instance=books,many=True)
        # 如果序列化多条,many=True(也就是queryset对象,就需要写)
        print(bookser.data,type(bookser.data))
        response[data] = bookser.data
        return Response(response)
技术图片

    高级用法:SerializerMethodField搭配方法使用(get_字段名)  write_only 反序列化的时候该字段前端不显示  read_only 反序列化的时候前端可以不传这个字段

技术图片
自定义py文件下的序列化组件 类下

from rest_framework import serializers  # 序列化组件
from app01 import models

class BookSerializer(serializers.Serializer):
    #序列化出版社的详情,指定SerializerMethodField之后,可以对应一个方法,返回什么内容,publish_detail就是什么内容
    publish_detail = serializers.SerializerMethodField(read_only=True)
    #对应的方法固定写法get_字段名
    def get_publish_detail(self,obj):   #这个obj 就是app01.models.Book
        print(obj,type(obj))
        return name:obj.publish.name,city:obj.publish.city

    # 返回所有作者信息
    authors = serializers.SerializerMethodField(read_only=True)
    def get_authors(self,obj):
        return [name:author.name,age:author.age for author in obj.authors.all()]
技术图片

 

 

 

序列化的两种方式

 1 Serializers没有指定表模型

  source:指定要序列化那个字段,可以是字段,可以是方法

  SerializerMethodFields的用法

技术图片
方式1:
authors = serializer.SerializerMethodField()
def get_authors(self,obj):
    return name:obj.publish.name,city:obj.publish.city
   #拓展性差  如果要查询一张表完整数据 那要写很多kv键值对

方式2:
class AuthorSerializer(serializer.Serializer):
    name = serializer.CharField()
    age = serializer.CharField()

authors = serializer.SerializerMethodField()
def get_authors(self,obj):
    ret = AuthorSerializer(instance=obj.authors.all(),man=True) #instance是默认参数可以不写
    return ret.data
技术图片

 

 2 ModelSerializers:指定了表模型

  class Meta:  model=表模型  fields = (‘__all__‘)显示所有的字段  fields = (‘id‘,‘name‘)显示部分字段  exclude=[‘name‘] 排除这个字段其他内容都显示 不能和fields同时使用  depth=1跨表深度是1,官方建议不要超过10,个人建议不要超过3  重写某个字段 在Meta外部,重写某些字段,方式同Serializers

 

技术图片
class AuthorSerializer(serializers.Serializer):
    name = serializers.CharField()
    age = serializers.CharField()
    # class Meta:
        # fields = (‘__all__‘)    serializers木有这个meta方法 只有modelserializer有

class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Book     #哪一张模型表
        # fields = (‘nid‘,‘name‘) #显示的字段
        fields = (__all__)    #显示所有字段信息
        # exclude = [‘name‘]  #排除
        # depth=1
        # 深度是1,官方建议不要超过10,个人建议不要超过3
    category = serializers.CharField(source=get_category_display)
    authors = serializers.SerializerMethodField()
    def get_authors(self,obj):
        # 可以写列表生成式 如果是很多的话就要在生成式里面写很多   而且拓展性很差 可以继续写serializer
        ret=AuthorSerializer(instance=obj.authors.all(),many=True)
        return ret.data

    name5= serializers.CharField(source=name) #重写name字段 与meta同级别 方式和Serializers重写或者序列化组件一样
技术图片

 

 技术图片技术图片技术图片

 

 

反序列化

 1 使用继承了Serializers序列化类的对象,反序列化  在自己写的序列化类中重写create方法,反序列化  重写create放法,实现序列化

  在序列化类中:  序列化类中写create方法表里面需要什么字段还是要传什么字段

技术图片
from rest_framework import serializers  # 序列化组件
class BookSerializer(serializers.Serializer):
    #反序列化创建
    def create(self, validated_data):
        ret = models.Book.objects.create(**validated_data)
        return ret
技术图片

  在视图中:

技术图片
from app01.app01serializer import BookSerializer    #自定义py文件里为了和view视图函数隔离开 自定义文件就写serializer组件

class Books(APIView):
    #使用Serializers序列化类的对象,反序列化
    def post(self,request):
        #实例化产生一个序列化类的对象,data是要反序列化的字典
        bookser = BookSerializer(data=request.data)
        if bookser.is_valid():
            #清洗通过的数据
            ret = bookser.create(bookser.validated_data)
        return Response()
技术图片

 

 

2 使用继承了ModelSerializers序列化类的对象,反序列化

  在视图中  在视图中写save() 表里面需要什么字段还是要传什么字段

技术图片
from django.shortcuts import render,HttpResponse,redirect

from rest_framework.views import APIView
from app01 import models

from rest_framework.response import Response    #返回用的

# 把对象转成json格式字符串
from app01.app01serializer import BookSerializer    #自定义py文件里为了和view视图函数隔离开 自定义文件就写serializer组件

class Books(APIView):

    # 使用继承了ModelSerializers序列化类的对象,反序列化
    def post(self,request):
        #实例化产生一个序列化类的对象,data是要反序列的字典
        bookser = BookSerializer(data=request.data)
        if bookser.is_valid(raise_exception=True):  #抛出的异常前端可以看到
            #清洗通过的数据
            bookser.save()
技术图片

 

 

反序列化的校验

反序列化的校验局部校验   validate_字段名(self,value):

  如果校验失败,抛出ValidationError(抛出的异常信息需要去视图层bookser.errors中取)

  如果校验通过直接return value

技术图片
from rest_framework import exceptions

序列化类下面写:
    #反序列化的校验(局部校验,全局校验)
    def validate_name(self,value):

        print(value)
        raise exceptions.ValidationError(不能以sb开头)
        # if value.startswith(‘sb‘):
        #     raise ValidationError(‘不能以sb开头‘)
        # return value
技术图片
技术图片
视图层 post请求内    校验错误信息
   def post(self,request):
        #实例化产生一个序列化类的对象,data是要反序列化的字典
        bookser=BookSerializer(data=request.data)
        # bookser.data
        if bookser.is_valid(raise_exception=True):
            #清洗通过的数据
            bookser.save()
        else:
            print(bookser.errors[name][0])
        return Response()
技术图片

 

 

反序列化的校验全局  validate(self,attrs)  attrs所有校验通过的数据,是个字典  如果校验失败,抛出ValidationError  如果校验通过直接返回return attrs

技术图片
序列化组件类中
    #去局校验
    def validate(self,attrs):
        print(attrs)

        return attrs
技术图片

 

 

独源码分析

 

全局和局部钩子源码部分

在序列化的时候,传many=True和many=False,生成的对象并不是一个对象

bookse.data  之前执行过,直接返回

        get_attribute(instance,self.source_attrs)

         self.source_attrs 是source指定的通过,切分后的列表

          instance 当前循环到的book对象

 

以上是关于序列化组件的主要内容,如果未能解决你的问题,请参考以下文章

Django框架(十九)—— 序列化组件(serializer)

第三章drf框架 - 序列化组件 | Serializer

Django自带序列化组件;分页器;Forms组件

序列化组件

基于Django的Rest Framework框架的序列化组件

序列化组件