zoukankan      html  css  js  c++  java
  • rest_framework序列化组件

    rest_framework序列化组件

    rest_framework序列化组件是干啥的?

    rest_framework序列化组件就是将需要其他数据类型都转成字符串

    项目有前后端分离和前后端不分离的,前后端不分离的项目可以通过模板语法直接将后端的变量,对象传给前端,前端可以直接使用,而前后端分离的项目就是后端只写逻辑不管前端,只需要提供接口就行了,并且整个后端不同的模块可以由不同的语言编写,那么他们怎么和前端交互呢?那就是字符串,字符串是所有语言通用的一个数据类型。


    如何使用drf的序列化组件

    1,先建表,完成表的迁移

    执行 python manage.py makemigrations 和 python manage.py migrate

    class Books(models.Model):
        name = models.CharField(max_length=32)
        author = models.CharField(max_length=32)
        xxx = models.CharField(max_length=32)
        ooo = models.CharField(max_length=32)
        publish = models.ForeignKey('Publish',null=True)
        def add(self):
            return self.name +':'+ self.author
    class Publish(models.Model):
        name=models.CharField(max_length=32)
        email=models.EmailField()
        # def __str__(self):
        #     return self.name

    2,新建一个序列化类,

    序列化类有两种,一种继承serializers,一种继承ModelSerializer

    from app01 import models
    from rest_framework import serializers

    class
    Publish_ser(serializers.Serializer): name = serializers.CharField() email = serializers.EmailField() class BookSerializer(serializers.Serializer): id = serializers.CharField() title = serializers.CharField(source='name')#source='name'表示序列化表的name字段,title表示把name改成title来显示 author = serializers.CharField()#默认序列化author字段并且显示的也是author publish = serializers.CharField() xxx = serializers.CharField(source='add') publish_dic = serializers.SerializerMethodField() def get_publish_dic(self,obj):#obj就是当前的Books这个表对象 return {'name':obj.publish.name,'email':obj.publish.email

    继承serializers的序列化类必须写需要序列化的字段,可以用source改显示的名字,

    source:可以指定字段source='name'   可以跨表source=publish.name,也可以指定方法source='add'

    read_only=True:反序列化时,不传,就是说这个字段不需要前端传过来,后端自己生成,比如用户创建的时间createtime
    write_only=True:序列化时,不显示,write_only表示只能写,不能读。例如定义序列化器时,password字段(还有短信验证码等)通常指定write_only=True。在序列化时,即对象转为字典、JSON字符串时,字典、JSON字符不会包含这个字段。

    就是说前端向后端取数据时不显示出来,比如我们登录的qq是找不到密码的显示的。

    class BookModelerializer(serializers.ModelSerializer):
        class Meta:
            model = models.Books #指定表模型
            fields = '__all__'
            # depth = 1
        publish = serializers.CharField(source='publish.name')
        publish_dic = serializers.SerializerMethodField()
    
        def get_publish_dic(self,obj):
            publish_list = models.Publish.objects.all()
            publish_ser = Publish_ser(instance=publish_list,many=True)
            return publish_ser.data
        name = serializers.CharField(max_length=5,min_length=2,error_messages={
            'max_length':'太长了',
            'min_length':'太短了',
        })
        def validate_name(self, value):
            from rest_framework import exceptions
            if value.startswith('sb'):
                raise exceptions.ValidationError('铭感词会')
            return value

    继承ModelSerializer的序列化类需要指定表模型关键字model,还要指定需要序列化的字段,关键字fields,

    fields = "__all__"表示将全部的字段都序列化,显示的就是每个字段具体的值,publish显示的是数字,要想显示publish表具体的数据有两种方法,

    1):可配置depth=1,显示深度为1表示会显示出其深度为1的关联表,depth推荐最大不要超过3;

    2):还可以使用SerializerMethodField,如上publish_dic字段,使用它后后面必须定义一个 get_"字段名"  的函数,这个函数的返回值就会当成publish_dic的值。

    如果想重写字段,在class:Meta上面或者下面写:name=serialzier.CharField(source='字段,方法,对象.字段'),这样会把原来的name字段覆盖掉,也可以写全新的字段比如publish_dic

    fields = ('name','author')表示只序列化name和author字段,

    在此基础上我们如果想在添加一个字段,publish = serializers.CharField(source='publish.name'),那么就必须把publish加入到fields里面fields = ('name','author','publish')不然会报错

    AssertionError: The field 'publish' was declared on serializer BookModelerializer, but has not been included in the 'fields' option.

    AssertionError:字段'publish_dic'在序列化程序BookModelerializer上声明,但未包含在'fields'选项中。

    exclude=('name')表示除了name字段,其他字段都序列化

     

    3,在视图中使用序列化的类

                -1 实例化序列化的类产生对象,在产生对象的时候,传入需要序列化的对象(queryset)
                -2 对象.data
                -3 return Response(对象.data)

    class Books(APIView):
        def get(self,request,*args,**kwargs):
            book_list = models.Books.objects.all()
            data = {'code': 333, 'msg': '请求成功',}
            # book_ser = mySer.BookSerializer(book_list,many=True)
            book_ser = mySer.BookModelerializer(book_list,many=True)
            data['books'] = book_ser.data
            return Response(data)#返回的字典比较美观,做了格式化
            # return HttpResponse(json.dumps(data,ensure_ascii=False))#返回的字典挤到一堆,不方便看
        def post(self,request,*args,**kwargs):
            print(request.data)
            response = {'code':333,'msg':'新增成功'}
            #提交的字典
            book = request.data
            #传统方法创建对象保存
            #新方法,通过序列化组件保存
            book_ser = mySer.BookModelerializer(data=book)
            if book_ser.is_valid():
                book_ser.save()
            else:
                response['msg'] = '新增失败'
                response['error'] = book_ser.errors
            response['data'] = book_ser.data
            return Response(response)
    
    class Book(APIView):
        def get(self,request,id,*args,**kwargs):
            data = {'code': 200, 'msg': '请求成功',}
            book_list = models.Books.objects.filter(pk=id).first()
            if book_list:
                book_ser = mySer.BookSerializer(book_list,many=False)
                data['books'] = book_ser.data
            else:
                data['msg'] = '请求的资源不存在'
                data['code'] = '111'
            return Response(data)

    book_ser = mySer.BookModelerializer(book_list,many=True)

    many:如果要序列化的对象book_list是一个queryset对象那么就要用many=Ture,如果是单个对象,那就需要many=False

    序列化的两种方式
            Serializers:没有指定表模型
                -source:指定要序列化哪个字段,可以是字段,可以是方法
                - SerializerMethodField的用法
                    authors=serializers.SerializerMethodField()
                    def get_authors(self,obj):
                         ret=AuthorSerializer(instance=obj.authors.all(),many=True)
                         return ret.data
                
            -ModelSerializers:指定了表模型
                class Meta:
                    model=表模型
                    #要显示的字段
                    fields=('__all__')
                    fields=('id','name')
                    #要排除的字段
                    exclude=('name')
                    #深度控制
                    depth=1
                -重写某个字段
                    在Meta外部,重写某些字段,方式同Serializers

    反序列化

    使用继承了Serializers序列化类的对象,反序列化
                -在自己写的序列化类中重写create方法
                -重写create方法,实现序列化
                    -在序列化类中:
                        def create(self, validated_data):
                            ret=models.Book.objects.create(**validated_data)
                            return ret
                    -在视图中:
                        def post(self,request):
                            bookser=BookSerializer(data=request.data)
                            if bookser.is_valid():
                                ret=bookser.create(bookser.validated_data)
                            return Response()
                
    使用继承了ModelSerializers序列化类的对象,反序列化
                -在视图中:
                    def post(self,request):
                        bookser=BookSerializer(data=request.data)
                        if bookser.is_valid():
                            ret=bookser.save()
                        return Response()
                
        -反序列化的校验
            -validate_字段名(self,value):
                -如果校验失败,抛出ValidationError(抛出的异常信息需要去bookser.errors中取)
                -如果校验通过直接return value
            -validate(self,attrs)
                -attrs所有校验通过的数据,是个字典
                -如果校验失败,抛出ValidationError
                -如果校验通过直接return attrs
                
        -读一读源码
            -全局和局部钩子源码部分
            -在序列化的时候,传many=True和many=False,生成的对象并不是一个对象
            -bookser.data
                -之前执行过,直接返回
                -get_attribute(instance, self.source_attrs)
                    -self.source_attrs 是source指定的通过 . 切分后的列表
                    -instance 当前循环到的book对象


       

  • 相关阅读:
    离散型随机变量及其分布列
    建立概率模型
    几何概型习题
    古典概型习题
    含绝对值符号的问题
    临界状态在数学中的应用
    古典概型中的几何体计数
    条件概率
    创建可以滚动的表格
    NoSQL数据库种类
  • 原文地址:https://www.cnblogs.com/tuanzibuku/p/11123672.html
Copyright © 2011-2022 走看看