解析模塊

解析模塊

一 、源解析器的做用

根據請求頭content-type選擇對應的解析器對請求體內容進行處理。有application/jsonx-www-form-urlencodedform-data等格式css

二 、源全局使用解析器

  • 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-typeapplication/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-typeapplication/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-typemultipart/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自動進行比對,並使用對應parserhtml

  • 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請求,響應內容')

四 、源碼分析

# 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)
# 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.2vue/cli 3 配置jQuery

vue.config.js中配置(沒有,手動項目根目錄下新建)vue

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@3

4.4 vue/cli 3 配置BootStrap

main.js中配置python

import "bootstrap"
import "bootstrap/dist/css/bootstrap.css"
相關文章
相關標籤/搜索