rest-framework之解析器
                                                            生活随笔
收集整理的這篇文章主要介紹了
                                rest-framework之解析器
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.                        
                                rest-framework之解析器
本文目錄
- 一 解析器的作用
- 二 全局使用解析器
- 三 局部使用解析器
- 四 源碼分析
一 解析器的作用
根據請求頭 content-type 選擇對應的解析器對請求體內容進行處理。
有application/json,x-www-form-urlencoded,form-data等格式
回到目錄二 全局使用解析器
setting里
REST_FRAMEWORK = {'DEFAULT_PARSER_CLASSES':['rest_framework.parsers.JSONParser''rest_framework.parsers.FormParser''rest_framework.parsers.MultiPartParser']}
路由:
urlpatterns = [url(r'test/', TestView.as_view()), ]
視圖函數:
from rest_framework.views import APIView from rest_framework.response import Responseclass 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請求,響應內容')
?
?
回到目錄三 局部使用解析器
a. 僅處理請求頭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請求,響應內容')    b.?僅處理請求頭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請求,響應內容')    c.?僅處理請求頭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><meta charset="UTF-8"> <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>    d. 僅上傳文件
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><meta charset="UTF-8"> <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>    e. 同時多個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請求,響應內容')
    ?
回到目錄四 源碼分析
1 在調用request.data時,才進行解析,由此入手@propertydef data(self):if not _hasattr(self, '_full_data'):self._load_data_and_files()return self._full_data2 查看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 parserreturn None4 最終調用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 defaultsval = self.defaults[attr]# Coerce import strings into classesif attr in self.import_strings:val = perform_import(val, attr)# Cache the result self._cached_attrs.add(attr)setattr(self, attr, val)return val5 user_settings方法 ,通過反射去setting配置文件里找REST_FRAMEWORK屬性,找不到,返回空字典@propertydef user_settings(self):if not hasattr(self, '_user_settings'):self._user_settings = getattr(settings, 'REST_FRAMEWORK', {})return self._user_settings
?
轉載于:https://www.cnblogs.com/di2wu/p/10141103.html
總結
以上是生活随笔為你收集整理的rest-framework之解析器的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 谁有魔道祖师未删减版本,跪求
- 下一篇: 中通快递多少钱一公斤啊?
