• 解析模块


    解析模块

    一 、源解析器的作用

    根据请求头content-type选择对应的解析器对请求体内容进行处理。有application/jsonx-www-form-urlencodedform-data等格式

    二 、源全局使用解析器

    -settings.py配置

    REST_FRAMEWORK = {
        'DEFAULT_PARSER_CLASSES':[
            'rest_framework.parsers.JSONParser'
            'rest_framework.parsers.FormParser'
            'rest_framework.parsers.MultiPartParser'
        ]
    }
    

    -urls.py配置

    urlpatterns = [
        url(r'test/', TestView.as_view()),
    ]
    

    -views.py

    from rest_framework.views import APIView
    from rest_framework.response import Response
    
    class TestView(APIView):
        def post(self, request, *args, **kwargs):
            print(request.content_type)
    
            # 获取请求的值,并使用对应的JSONParser进行处理
            print(request.data)
            """
            application/x-www-form-urlencoded 或 
            multipart/form-data时,request.POST中才有值
            """
            print(request.POST)
            print(request.FILES)
            return Response('POST请求,响应内容')
    
        def put(self, request, *args, **kwargs):
            return Response('PUT请求,响应内容')
        
    

    三 、源局部使用解析器

    3.1 content-type为application/json

    -``urls.py`

    from django.conf.urls import url, include
    from web.views.s5_parser import TestView
    
    urlpatterns = [
        url(r'test/', TestView.as_view(), name='test'),
    ]
    
    

    -views.py

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from rest_framework.views import APIView
    from rest_framework.response import Response
    from rest_framework.request import Request
    from rest_framework.parsers import JSONParser
    
    
    class TestView(APIView):
        parser_classes = [JSONParser, ]
    
        def post(self, request, *args, **kwargs):
            print(request.content_type)
    
            # 获取请求的值,并使用对应的JSONParser进行处理
            print(request.data)
    		"""
            application/x-www-form-urlencoded 或 
            multipart/form-data时,request.POST中才有值
            """
            print(request.POST)
            print(request.FILES)
    
            return Response('POST请求,响应内容')
    
        def put(self, request, *args, **kwargs):
            return Response('PUT请求,响应内容')
            
    

    3.2 content-type为application/x-www-form-urlencoded

    -urls.py

    from django.conf.urls import url, include
    from web.views import TestView
    
    urlpatterns = [
        url(r'test/', TestView.as_view(), name='test'),
    ]
    
    

    -views.py

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from rest_framework.views import APIView
    from rest_framework.response import Response
    from rest_framework.request import Request
    from rest_framework.parsers import FormParser
    
    
    class TestView(APIView):
        parser_classes = [FormParser, ]
    
        def post(self, request, *args, **kwargs):
            print(request.content_type)
    
            # 获取请求的值,并使用对应的JSONParser进行处理
            print(request.data)
    
            """
            application/x-www-form-urlencoded 或 
            multipart/form-data时,request.POST中才有值
            """
            print(request.POST)
            print(request.FILES)
    
            return Response('POST请求,响应内容')
    
        def put(self, request, *args, **kwargs):
            return Response('PUT请求,响应内容')
    
    

    3.3 content-type为multipart/form-data

    • urls.py
    from django.conf.urls import url, include
    from web.views import TestView
    
    urlpatterns = [
        url(r'test/', TestView.as_view(), name='test'),
    ]
    
    

    -views.py

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from rest_framework.views import APIView
    from rest_framework.response import Response
    from rest_framework.request import Request
    from rest_framework.parsers import MultiPartParser
    
    
    class TestView(APIView):
        parser_classes = [MultiPartParser, ]
    
        def post(self, request, *args, **kwargs):
            print(request.content_type)
    
            # 获取请求的值,并使用对应的JSONParser进行处理
            print(request.data)
            """
            application/x-www-form-urlencoded 或 
            multipart/form-data时,request.POST中才有值
            """
            print(request.POST)
            print(request.FILES)
            return Response('POST请求,响应内容')
    
        def put(self, request, *args, **kwargs):
            return Response('PUT请求,响应内容')
    
    

    -templete.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        
        <title>Title</title>
    </head>
    <body>
    <form action="http://127.0.0.1:8000/test/" method="post" enctype="multipart/form-data">
        <input type="text" name="user" />
        <input type="file" name="img">
    
        <input type="submit" value="提交">
    
    </form>
    </body>
    </html>
    

    3.4 仅上传文件

    -urls.py

    from django.conf.urls import url, include
    from web.views import TestView
    
    urlpatterns = [
        url(r'test/(?P<filename>[^/]+)', TestView.as_view(), name='test'),
    ]
    

    -views.py

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from rest_framework.views import APIView
    from rest_framework.response import Response
    from rest_framework.request import Request
    from rest_framework.parsers import FileUploadParser
    
    
    class TestView(APIView):
        parser_classes = [FileUploadParser, ]
    
        def post(self, request, filename, *args, **kwargs):
            print(filename)
            print(request.content_type)
    
            # 获取请求的值,并使用对应的JSONParser进行处理
            print(request.data)
            """
            application/x-www-form-urlencoded 或 
            multipart/form-data时,request.POST中才有值
            """
            print(request.POST)
            print(request.FILES)
            return Response('POST请求,响应内容')
    
        def put(self, request, *args, **kwargs):
            return Response('PUT请求,响应内容')
    
    

    -templete.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        
        <title>Title</title>
    </head>
    <body>
    <form action="http://127.0.0.1:8000/test/f1.numbers" method="post" enctype="multipart/form-data">
        <input type="text" name="user" />
        <input type="file" name="img">
    
        <input type="submit" value="提交">
    
    </form>
    </body>
    </html>
    
    

    3.5 同时多个Parser

    当同时使用多个parser时,rest framework会根据请求头content-type自动进行比对,并使用对应parser

    -urls.py

    from django.conf.urls import url, include
    from web.views import TestView
    
    urlpatterns = [
        url(r'test/', TestView.as_view(), name='test'),
    ]
    
    

    -views.py

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from rest_framework.views import APIView
    from rest_framework.response import Response
    from rest_framework.request import Request
    from rest_framework.parsers import JSONParser, FormParser, MultiPartParser
    
    
    class TestView(APIView):
        parser_classes = [JSONParser, FormParser, MultiPartParser, ]
    
        def post(self, request, *args, **kwargs):
            print(request.content_type)
    
            # 获取请求的值,并使用对应的JSONParser进行处理
            print(request.data)
            """
            application/x-www-form-urlencoded 或 
            multipart/form-data时,request.POST中才有值
            """
            print(request.POST)
            print(request.FILES)
            return Response('POST请求,响应内容')
    
        def put(self, request, *args, **kwargs):
            return Response('PUT请求,响应内容')
            
    

    四 、源码分析

    4.1 request解析

    """
    1 在调用request.data时,才进行解析,由此入手
    """
    @property
    def data(self):
        if not _hasattr(self, '_full_data'):
            self._load_data_and_files()
        return self._full_data
            
    """
    2 查看self._load_data_and_files()方法
    	---->
    	self._data, self._files = self._parse()
    """
    
        def _parse(self):
            #用户请求头里content_type的值
            media_type = self.content_type
    		"""
    		self.parsers 就是用户配置的
    		parser_classes=[FileUploadParser,FormParser]
    		"""
            #self里就有content_type,传入此函数
            parser = self.negotiator.select_parser(self, 
                							self.parsers)
    
    """
    3 查看self.negotiator.select_parser(self, self.parsers)
    """
    def select_parser(self, request, parsers):
        """同过media_type和request.content_type比较,
        来返回解析器,然后调用解析器的解析方法"""
        # 每个解析器都有media_type = 'multipart/form-data'属性
        for parser in parsers:
    		if media_type_matches(
    							parser.media_type, 
                				 request.content_type):
    			return parser
    			
    		return None
        
    """
    4 最终调用parser的解析方法来解析
    parsed = parser.parse(stream, 
                          media_type, 
                          self.parser_context)
    """
    

    4.2 request实例化

    # 1 Request实例化,parsers=self.get_parsers()
    Request(
        request,
        parsers=self.get_parsers(),
        authenticators=self.get_authenticators(),
        negotiator=self.get_content_negotiator(),
        parser_context=parser_context
    )
    
    # 2 get_parsers方法,循环实例化出self.parser_classes中类对象
    def get_parsers(self):
        return [parser() for parser in self.parser_classes]            
    
    # 3 self.parser_classes 先从类本身找,找不到去父类找即APIVIew 中的
    parser_classes = api_settings.DEFAULT_PARSER_CLASSES
    
    # 4 api_settings是一个对象,对象里找DEFAULT_PARSER_CLASSES属性,
    # 找不到,会到getattr方法
    def __getattr__(self, attr):
    	if attr not in self.defaults:
    		raise AttributeError(
    			"Invalid API setting: '%s'" % attr
    			)
    
    	try:
    		# 调用self.user_settings方法,
    		# 返回一个字典,字典再取attr属性
    		val = self.user_settings[attr]
    	except KeyError:
    		# Fall back to defaults
    		val = self.defaults[attr]
    
    	# Coerce import strings into classes
    	if attr in self.import_strings:
    		val = perform_import(val, attr)
    
    	# Cache the result
    	self._cached_attrs.add(attr)
    	setattr(self, attr, val)
    	return val
    	
    """
    5 user_settings方法 ,通过反射去setting配置
    文件里找REST_FRAMEWORK属性,找不到,返回空字典
    """
    @property
    def user_settings(self):
    	if not hasattr(self, '_user_settings'):
    		self._user_settings = getattr(settings, 
    									 'REST_FRAMEWORK', 
    									 {}
    									 )
    	return self._user_settings
            
    

    4.1 jQuery安装

    >: cnpm install jquery
    

    4.2 vue/cli 3 配置 jQuery

    vue.config.js中配置(没有,手动项目根目录下新建)

    const webpack = require("webpack");
    
    module.exports = {
        configureWebpack: {
            plugins: [
                new webpack.ProvidePlugin({
                    $: "jquery",
                    jQuery: "jquery",
                    "window.jQuery": "jquery",
                    Popper: ["popper.js", "default"]
                })
            ]
        }
    };
    

    4.3 BootStrap安装

    >: cnpm install bootstrap
    

    4.4 vue/cli 3 配置BootStrap

    main.js中配置

    import "bootstrap"
    import "bootstrap/dist/css/bootstrap.css"
    
  • 相关阅读:
    无法嵌入互操作类型“-----”。请改用适用的接口
    DataGridView 控件用法(可能不是很全面,因为这是自己常常用到的一些小总结):
    实例化新的一个(new)
    用户 'sa' 登录失败。 (Microsoft SQL Server,错误: 18456)
    开始安装 ASP.NET (4.0.30319.18408)。 出现了错误: 0x8007b799 必须具有此计算机的管理员权限才能运行此工具
    Web 应用程序项目 MvcApplication1 已配置为使用 IIS。
    命名空间中的“MvcBuildViews”。 无效
    SQLServer存储过程入门
    golang fmt格式“占位符”
    go语言基本运算符
  • 原文地址:https://www.cnblogs.com/Dr-wei/p/11735471.html
Copyright © 2020-2023  润新知