解析模块

解析模块

一 、源解析器的作用

根据请求头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"
posted @ 2019-10-24 22:32  つつつつつつ  阅读(205)  评论(0编辑  收藏  举报