• Django rest framework(5)----解析器


    解析器的主要作用:对用户请求体中的数据进行解析

    解析器前戏

    有时候我们在接受前端传送的值的时候,会存在这样一个奇怪的现象使用request.body可以取到值,而使用request.POST的时候去不到值,基于这样的情况,究竟是如何造成的呢?

    追了以下源码发现  把request.body  中的值转换成 POST 需要满足以下的两个条件,也就是说必须满足以下两个条件,才可以使用request.POST接受值,否则只能使用request.body

    1. 请求头要求:
         Content-Type: application/x-www-form-urlencoded
         PS: 如果请求头中的 Content-Type: application/x-www-form-urlencoded,request.POST中才有值(去request.body中解析数据)。
    2. 数据格式要求:
         name=alex&age=18&gender=男

    PS 以上的两个条件缺一不可

    部分源码如下

     一般在那些地方默认可以使用request.POST 接受的呢

    表单提交:

    a. form表单提交
        <form method...>
            input...
            
        </form>

      

    ajax 提交的数据。headers content-type使用默认类型的

    $.ajax({
        url:...
        type:POST,
        data:{name:alex,age=18} # 内部转化 name=alex&age=18&gender=男
    })
    

    这样的情况是 request.body有值;request.POST无值,如果我们需要取值的话可以这样做   json.loads(request.body)

    $.ajax({
        url:...
        type:POST,
        headers:{'Content-Type':"application/json"}
        data:JSON.stringfy({name:alex,age=18}) # {name:alex,age:18...}
    })
    

      

    以上的情况判断去使用的时候,我们需要去辨别 headers 中的请求类型,那么有没有一种好的方式,使一切变得简单一些呢,当然下面直接上代码有一个清晰的认识在来追踪它的源码

    restframework--解析器使用  

    类视图代码如下:

    from rest_framework.parsers import JSONParser,FormParser
    
    class ParserView(APIView):
        parser_classes = [JSONParser,FormParser,]
        """
        JSONParser:表示只能解析content-type:application/json头
        JSONParser:表示只能解析content-type:application/x-www-form-urlencoded头
        """
    
        def post(self,request,*args,**kwargs):
            """
            允许用户发送JSON格式数据
                a. content-type: application/json
                b. {'name':'alex',age:18}
            :param request:
            :param args:
            :param kwargs:
            :return:
            """
            """
            1. 获取用户请求
            2. 获取用户请求体
            3. 根据用户请求头 和 parser_classes = [JSONParser,FormParser,] 中支持的请求头进行比较
            4. JSONParser对象去请求体
            5. request.data
            """
            print(request.data)
    
    
            return HttpResponse('ParserView')

    添加url

    url(r'parser/$', views.ParserView.as_view()), 

    发送 表单的数据

    后台打印的数据如下

    发送json类型的数据

    后台接受打印的数据如下

    源码流程

    入口  dispatch 

    def dispatch(self, request, *args, **kwargs):
            """
            `.dispatch()` is pretty much the same as Django's regular dispatch,
            but with extra hooks for startup, finalize, and exception handling.
            """
            self.args = args
            self.kwargs = kwargs
            #对原始request进行加工,丰富了一些功能
            #Request(
            #     request,
            #     parsers=self.get_parsers(),
            #     authenticators=self.get_authenticators(),
            #     negotiator=self.get_content_negotiator(),
            #     parser_context=parser_context
            # )
            #request(原始request,[BasicAuthentications对象,])
            #获取原生request,request._request
            #获取认证类的对象,request.authticators
            #1.封装request
            request = self.initialize_request(request, *args, **kwargs)
            self.request = request
            self.headers = self.default_response_headers  # deprecate?
    
            try:
                #2.认证
                self.initial(request, *args, **kwargs)
    
                # Get the appropriate handler method
                if request.method.lower() in self.http_method_names:
                    handler = getattr(self, request.method.lower(),
                                      self.http_method_not_allowed)
                else:
                    handler = self.http_method_not_allowed
    
                response = handler(request, *args, **kwargs)
    
            except Exception as exc:
                response = self.handle_exception(exc)
    
            self.response = self.finalize_response(request, response, *args, **kwargs)
            return self.response

    initialize_request 获取所有解析器

    def initialize_request(self, request, *args, **kwargs):
            """
            Returns the initial request object.
            """
            parser_context = self.get_parser_context(request)
    
            return Request(
                request,
                parsers=self.get_parsers(),                  #获取所有的解析器
                authenticators=self.get_authenticators(),    #[BasicAuthentication(),],把所有的认证类对象封装到request里面了
                negotiator=self.get_content_negotiator(),
                parser_context=parser_context
            )

    get_parsers 获取解析对象的列表

     def get_parsers(self):
            """
            Instantiates and returns the list of parsers that this view can use.
            """
            return [parser() for parser in self.parser_classes]

    parser_classes

     

     同样我们可以在settings里面全局配置,我们一般使用的就是全局的配置

    REST_FRAMEWORK = {
        #版本
        "DEFAULT_VERSIONING_CLASS":"rest_framework.versioning.URLPathVersioning",   
        #解析器
        "DEFAULT_PARSER_CLASSES":["rest_framework.parsers.JSONParser","rest_framework.parsers.FormParser"]
    }
  • 相关阅读:
    让EditPlus支持SQL高亮提示
    SQL Server 触发器
    asp.net中使用Global.asax文件中添加应用出错代码,写入系统日志文件或数据库
    C#钩子类 几乎捕获键盘鼠标所有事件
    DataGridView一些常用操作
    在C#中实现串口通信的方法
    System.Diagnostics.Process.Start的妙用
    Byte[]、Image、Bitmap 之间的相互转换
    Dos命令打印文件以及Dos打印到USB打印端口
    Winform常用的一些功能收集(持续更新)
  • 原文地址:https://www.cnblogs.com/crazymagic/p/9557733.html
Copyright © 2020-2023  润新知