解析模塊
1、解析器的作用
根據請求頭 content-type 選擇對應的解析器對請求體內容進行處理。
有application/json,x-www-form-urlencoded,form-data等格式
2、全局使用解析器
- 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()),
]
- 視圖函數
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、局部使用解析器
3-1 僅處理請求頭content-type為application/json的請求體
from django.conf.urls import url, include
from web.views.s5_parser import TestView
urlpatterns = [
url(r'test/', TestView.as_view(), name='test'),
]
#!/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 的請求體
from django.conf.urls import url, include
from web.views import TestView
urlpatterns = [
url(r'test/', TestView.as_view(), name='test'),
]
#!/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的請求體
from django.conf.urls import url, include
from web.views import TestView
urlpatterns = [
url(r'test/', TestView.as_view(), name='test'),
]
#!/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請求,響應內容')
<!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 僅上傳文件
from django.conf.urls import url, include
from web.views import TestView
urlpatterns = [
url(r'test/(?P<filename>[^/]+)', TestView.as_view(), name='test'),
]
#!/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請求,響應內容')
<!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
from django.conf.urls import url, include
from web.views import TestView
urlpatterns = [
url(r'test/', TestView.as_view(), name='test'),
]
#!/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.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
jQuery
>: cnpm install jquery
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"]
})
]
}
};
BootStrap
>: cnpm install bootstrap@3
vue/cli 3 配置BootStrap:在main.js中配置
import "bootstrap"
import "bootstrap/dist/css/bootstrap.css"