• 序列化组件


    序列化组件

    序列化之Serializers

    序列化

    models部分

    from django.db import models
    
    # Create your models here.
    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(null=True)
        xx=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 'xxx'
    
    
    class Author(models.Model):
        nid = models.AutoField(primary_key=True)
        name = models.CharField(max_length=32)
        age = models.IntegerField()
    
    
    
    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()
    
        def __str__(self):
            return self.name
    
    

    在app01下新建一个py文件,这里命名为app01serilaizer

    app01serializer部分

    from app01 import models
    from rest_framework import serializers
    class AuthorSerializer(serializers.Serializer):
        name=serializers.CharField()
        age=serializers.CharField()
        
    class BookSerializer(serializers.Serializer):
        #指定source='name' ,表示序列化模型表中的name字段,重名命为name5(name和source='name'指定的name不能重名)
        name5=serializers.CharField(source='name')
    #     #write_only 序列化的时候,该字段不显示
    #     #read_only 反序列化的时候,该字段不传
        price=serializers.CharField(write_only=True)
    #     #如果要取 出版社的city source='publish.city'
        publish=serializers.CharField(source='publish.name')
    #     #source不但可以指定一个字段,还可以指定一个方法
        book_type = serializers.CharField(source='get_xx_display',read_only=True)
    #     #序列化出版社的详情,指定SerializerMethodField之后,可以对应一个方法,返回什么内容,publish_detail就是什么内容
        publish_detail=serializers.SerializerMethodField(read_only=True)
        #对应的方法固定写法get_字段名
        def get_publish_detail(self,obj):
            # print(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()]
            authorser=AuthorSerializer(obj.authors.all(),many=True)  #拓展性强
            return authorser.data
    
        def create(self, validated_data):
            ret=models.Book.objects.create(**validated_data)
            return ret
    

    views部分

    from app01.app01serializer import BookSerializer
    class Books(APIView):
        def get(self,request):
            response={'code':100,'msg':'查询成功'}
            books=models.Book.objects.all()
            #如果序列化多条,many=True(也就是queryset对象,就需要写)
            #如果序列化一条(可以不写),instance是要序列化的对象
            bookser=BookSerializer(instance=books,many=True)
            # print(type(bookser.data))
            # bookser.data
            response['data']=bookser.data
            return Response(response)
    

    反序列化

    models部分不变

    views部分

     def post(self,request):
            #实例化产生一个序列化类的对象,data是要反序列化的字典
            # print(request.data)
            bookser=BookSerializer(data=request.data)
            if bookser.is_valid():
                #清洗通过的数据,可以加限制比如最大长度之类的
                ret=bookser.create(bookser.validated_data)  #重写create方法,更新的话用update
    
            return Response()
    

    序列化之ModelSerializers

    序列化

    app01serializers部分

    from rest_framework import serializers
    from rest_framework import exceptions
    from app01 import models
    
    class BookSerializer(serializers.ModelSerializer):
        class Meta:
            model=models.Book
            # fields=('nid','name')
            #不能跟fields同时使用
            # exclude=['name',]
            fields=('__all__')
            #深度是1,官方建议不要超过10,个人建议不要超过3
            # depth=1
        # xx=serializers.CharField(source='get_xx_display')  #在外面重写字段(取中文)
        # authors=serializers.SerializerMethodField()
        # def get_authors(self,obj):
        #     ret=AuthorSerializer(instance=obj.authors.all(),many=True)
        #     return ret.data
        # name=serializers.CharField()
        #反序列化的校验(局部校验,全局校验)
        def validate_name(self,value):
    
            print(value)
            raise exceptions.ValidationError('不能以sb开头')
            # if value.startswith('sb'):
            #     raise ValidationError('不能以sb开头')
            # return value
    
        def validate(self,attrs):
            print(attrs)
            # if attrs.get('price')!=attrs.get('xx'):
            #     raise exceptions.ValidationError('name和price相等,不正常')
            return attrs
    

    views部分

        def get(self,request):
            response={'code':100,'msg':'查询成功'}
            books=models.Book.objects.all()
            #了解
            # ret = serializers.serialize("json", books)
            #如果序列化多条,many=True(也就是queryset对象,就需要写)
            #如果序列化一条(可以不写),instance是要序列化的对象
            bookser=BookSerializer(instance=books,many=True)
            # print(type(bookser.data))
            # bookser.data
            response['data']=bookser.data
            return Response(response)
    

    反序列化

    views部分

      #使用继承了ModelSerializers序列化类的对象,反序列化
        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,value)
    	如果校验失败,抛出validationError(抛出的异常信息需要去bookser.errors中取)
    	如果校验通过直接return value
    
    validate(self,attrs)
    	attrs所有校验通过的数据,是个字典
    	如果校验失败,抛出validationError
    	如果校验通过直接return attrs
    

    源码分析

    序列化组件,先调用__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
    当参数传过去,判断是方法就加括号执行,是属性就把值取出来
    
  • 相关阅读:
    分享几个python小脚本
    关于python编译的一点小结
    一位测试工程师工作一年的心得体会
    Zookeeper知识梳理
    Kafka知识梳理(转载)
    霍夫曼编码压缩算法(转载 -- www.uusystem.com)
    表、栈和队列
    Python3正则表达式清洗Excel文档
    MongoDB学习笔记
    Centos--Docker应用
  • 原文地址:https://www.cnblogs.com/yanminggang/p/11123445.html
Copyright © 2020-2023  润新知