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

    #####序列化组件#####
    
    一、什么是序列化
        在python中一切皆对象,把对象从内存中变成可存储或传输的过程称之为序列化。
        你写一个django项目肯定是有前后端交互的吧,虽然django也可以自己写模板(也就是前端页面),你要给pc端,移动端用?难道要写两个django项目,这样
        是不是太浪费资源了,所以现在出了前后端分离,这样的话,你就写一个后端就好了,不管前端是移动端,还是pc端,我只负责传数据过就好了。出现前后端分离
        的方案,好处还有很多,就不一一多说。
        总之,我django项目只负责返回相应的数据就好了,这就存在数据传输了,我后端从硬盘拿到数据,是在内存中的,所以我需要把内存中的数据,转成一个中间
        格式(它可以进行传输),前端拿到后台传过去的数据后,再进行操作,将这个中间格式的数据,转成前端语言能看懂的数据类型就好了。
    
    二、反序列化和序列化就相反了,把中间格式转成数据类型,能够直接使用。
    
    三、那么就有一个问题了,在python中哪种类型,能在前端语言中使用呢?
            有那么一个,就是字典,它是这样的符号 {} ,在python中就是一个数据类型
            在前端js语言中 {} 这个代表着就是一个对象
       上面这个问题解决了,那么用哪种中间格式去进行传输呢?这个中间格式必须满足python和js都可以进行序列化,反序列化
       这个中间格式就是json,可能有其他的(不太清楚)
    
       有了上面两个问题的解决,那我们只需向前台传输json格式的字典就好了,列表套字典也可以,这才是重点!!!!!!
    
    四、如何在rest_framework中使用序列化呢?(Serializer的使用)
       from rest_framework import serializers   它所在的位置
       序列化组件的使用其实和forms组件的操作是差不多的,在app文件中新建一个py文件,拿来单独写序列化类。
    
        那我写一个图书的序列化,目的就是为什么要使用序列化的原因。
    
        在新建的py文件中:
        from rest_framework import serializers
    
        class BookSerializers(serializers.Serializer):
            name = serializers.CharField()
            price = serializers.CharField()
            author = serializers.CharField()
            publish = serializers.CharField()
    
        在视图层(views)文件中:
    
        class Book(APIView):
            def get(self,request):
                books = models.Book.objects.all()
                book_ser = BookSerializers(instance=books,many=True)
                book_dic = book_ser.data
                return JsonResponse(book_dic)
    
        这是很基础的序列化使用,book_ser.data这个的返回值就是一个字典
        写一个序列化类也很简单,写一个普通类,然后继承serializers.Serializer就好了
        下面就写写上面出现过的一些方法
        -----------------------------------------------------
        1、name = serializers.CharField()
        -----------------------------------------------------
        2、book_ser = BookSerializers(instance=books,many=True)
        -----------------------------------------------------
        3、book_ser.data
        -----------------------------------------------------
    
        先说name = serializers.CharField()这句,首先我们需要知道serializers是一个模块名(也就是py文件),
        上面这句代码,就相当于面向对象的组合,一个对象的属性的值是另一个对象。CharField是不是很熟悉(forms那块),用法的话,和forms组件有一些是相同
        的,写写CharField里的一个参数,source他可以等于表(表就是models文件里)的字段名,或者方法名,但是这个名字不能跟序列化类对应的属性名一样。
        比如:name = serializers.CharField(source='name')   这样是不对的。
        继续还有这样一种方法 name = serializers.SerializerMethodField(),但是要在该序列化类中写一个方法,方法名一定叫做get_name,它的返回值,
        就是name(这个name是序列化类的属性)所对应的值,方法的名字格式就是  get_序列化类属性的名字。
        也可以更改报错的语句  error_messages,和forms里一样
    
    
        再说book_ser = BookSerializers(instance=books,many=True)这句,这就是生成一个序列化类的对象,肯定会执行__init__这个方法的,那就一层
        一层找,这个__init__方法在哪里,传什么参数进去,最终我们在BaseSerializer这个类里找到了:
        BaseSerializer类
            def __init__(self, instance=None, data=empty, **kwargs):
                self.instance = instance
                if data is not empty:
                    self.initial_data = data
                self.partial = kwargs.pop('partial', False)
                self._context = kwargs.pop('context', {})
                kwargs.pop('many', None)
                super(BaseSerializer, self).__init__(**kwargs)
            def __new__(cls, *args, **kwargs):
                # We override this method in order to automagically create
                # `ListSerializer` classes instead when `many=True` is set.
                if kwargs.pop('many', False):
                    return cls.many_init(*args, **kwargs)
                return super(BaseSerializer, cls).__new__(cls, *args, **kwargs)
        上面说漏了,执行init方法之前,肯定会走new这个方法,我们看这个new方法,判断many的值是否为True or False,True的话,
        执行类的many_init(*args, **kwargs),False执行其基类的new方法。
        直接将many的作用吧:如果为真,那么book_ser.data就是一个列表里夹着字典,如果为假,那就是一个字典。它是通过判断many的值,再进行序列化的,
        假如你instance=books,这个books是一本书的对象,那么many就应该为false(不用传,默认为false),books是多个对象,那么就必须many为真了。
        如果你是序列化的话,那么instance就应该为你想序列化的对象,data必须为空,也就是不传。
        如果你想反序列化的话,也就是前台发送的数据是一个字典,那么data的值就是前端传来的字典,如果该请求是添加书籍的话,那么instance不用传,如果是
        修改书籍操作,那么instance就是该书籍的对象了,你不传哪本书,它怎么知道修改哪本呢?
    
    
        最后再讲book_ser.data这行代码,它的返回值就是字典或列表里套字典对吧,这取决于many的值
    
    
    五、ModelSerializer的使用,作用和Serializer一样。继续拿Book为例子
    
        class BookSerializers(serializers.ModelSerializer)
            class Meta:
                model = models.Book
                fields = '__all__'
    
        写完啦,效果和上面写的序列化类一样,在自定义序列化类中写一个类,名字必须为Meta,model指定是哪个表,fields = '__all__',全部字段,
        除了上面这些,exclude=('nid',),表示出来nid,其他所有字段,所以exclude和fields必须只能有一个。depth深度控制。
        虽然'__all__'已经规定完了所有字段的格式,你可以在下面重写你自己哪个字段想返回怎样的格式,比如:
        nid = serializers.CharField()  ---->>>意思是你可以再写,将前面的覆盖掉
    
    六、HyperlinkedIdentityField的使用
       作用:自动生成一个超链接(url)
    
       class BookSerializers(serializers.ModelSerializer)
        class Meta:
            model = models.Book
            fields = '__all__'
    
        publish = serializers.HyperlinkedIdentityField(view_name='zhu',lookup_field='publish_id',lookup_url_kwarg='pk')
    
        视图层:
            class Book(APIView):
            def get(self,request):
                books = models.Book.objects.all()
                book_ser = BookSerializers(instance=books,many=True,context={'request':request})
                book_dic = book_ser.data
                return JsonResponse(book_dic)
    
        路由层:
            url(r'books/',Book.as_view()),
            url(r'publish/(?P<pk>d+)/$',Publish.as_view(),name='zhu'),
    
        解释下上面HyperlinkedIdentityField传的参数view_name就是路由的name,通过反向解析可以拿到,lookup_field就是通过表的哪个字段,
        lookup_url_kwarg就是url中的关键字参数。大概流程是,通过view_name拿到url,把publish_id的值赋给那个关键字参数。
    
    
    七、校验字段和保存数据功能
        校验字段和forms组件一样,也有局部钩子,全局钩子,也是is_valid()这个方法进行校验,返回值为布尔类型,校验成功直接调用save方法,
        就会保存在数据库中,注意调用save之前,你要保证字段和你数据库中的字段要对得上才行。校验失败的话,errors这里是错误信息
  • 相关阅读:
    基于51的串行通讯原理及协议详解(uart)
    linux下各目录的作用
    firefox插件之 vimperator 的使用
    samba的使用
    debian系统下安装ssh服务
    Aircrack-ng 工具箱
    linux系统下静态IP的设置
    HTML 与 css 的简单学习
    微软亚洲实验室一篇超过人类识别率的论文:Delving Deep into Rectifiers: Surpassing Human-Level Performance on ImageNet Classification ImageNet Classification
    概率论中的一些常见的分布与公式
  • 原文地址:https://www.cnblogs.com/zhuchunyu/p/10132586.html
Copyright © 2011-2022 走看看