有時候咱們在接受前端傳送的值的時候,會存在這樣一個奇怪的現象使用request.body能夠取到值,而使用request.POST的時候去不到值,基於這樣的狀況,到底是如何形成的呢?前端
追瞭如下源碼發現 把request.body 中的值轉換成 POST 須要知足如下的兩個條件,也就是說必須知足如下兩個條件,纔可使用request.POST接受值,不然只能使用request.bodypython
1. 請求頭要求: Content-Type: application/x-www-form-urlencoded PS: 若是請求頭中的 Content-Type: application/x-www-form-urlencoded,request.POST中才有值(去request.body中解析數據)。 2. 數據格式要求: name=alex&age=18&gender=男
PS 以上的兩個條件缺一不可ajax
部分源碼以下json
通常在那些地方默承認以使用request.POST 接受的呢app
a. form表單提交 <form method...> input... </form>
$.ajax({ url:... type:POST, data:{name:alex,age=18} # 內部轉化 name=alex&age=18&gender=男 })
這樣的狀況是 request.body有值;request.POST無值,若是咱們須要取值的話能夠這樣作 json.loads(request.body)post
$.ajax({ url:... type:POST, headers:{'Content-Type':"application/json"} data:JSON.stringfy({name:alex,age=18}) # {name:alex,age:18...} })
以上的狀況判斷去使用的時候,咱們須要去辨別 headers 中的請求類型,那麼有沒有一種好的方式,使一切變得簡單一些呢,固然下面直接上代碼有一個清晰的認識在來追蹤它的源碼this
類視圖代碼以下:url
from rest_framework.parsers import JSONParser,FormParser class ParserView(APIView): parser_classes = [JSONParser,FormParser,] """ JSONParser:表示只能解析content-type:application/json頭 JSONParser:表示只能解析content-type:application/x-www-form-urlencoded頭 """ def post(self,request,*args,**kwargs): """ 容許用戶發送JSON格式數據 a. content-type: application/json b. {'name':'alex',age:18} :param request: :param args: :param kwargs: :return: """ """ 1. 獲取用戶請求 2. 獲取用戶請求體 3. 根據用戶請求頭 和 parser_classes = [JSONParser,FormParser,] 中支持的請求頭進行比較 4. JSONParser對象去請求體 5. request.data """ print(request.data) return HttpResponse('ParserView')
添加urlspa
url(r'parser/$', views.ParserView.as_view()),
發送 表單的數據3d
後臺打印的數據以下
發送json類型的數據
後臺接受打印的數據以下
入口 dispatch
def dispatch(self, request, *args, **kwargs): """ `.dispatch()` is pretty much the same as Django's regular dispatch, but with extra hooks for startup, finalize, and exception handling. """ self.args = args self.kwargs = kwargs #對原始request進行加工,豐富了一些功能 #Request( # request, # parsers=self.get_parsers(), # authenticators=self.get_authenticators(), # negotiator=self.get_content_negotiator(), # parser_context=parser_context # ) #request(原始request,[BasicAuthentications對象,]) #獲取原生request,request._request #獲取認證類的對象,request.authticators #1.封裝request request = self.initialize_request(request, *args, **kwargs) self.request = request self.headers = self.default_response_headers # deprecate? try: #2.認證 self.initial(request, *args, **kwargs) # Get the appropriate handler method if request.method.lower() in self.http_method_names: handler = getattr(self, request.method.lower(), self.http_method_not_allowed) else: handler = self.http_method_not_allowed response = handler(request, *args, **kwargs) except Exception as exc: response = self.handle_exception(exc) self.response = self.finalize_response(request, response, *args, **kwargs) return self.response
initialize_request 獲取全部解析器
def initialize_request(self, request, *args, **kwargs): """ Returns the initial request object. """ parser_context = self.get_parser_context(request) return Request( request, parsers=self.get_parsers(), #獲取全部的解析器 authenticators=self.get_authenticators(), #[BasicAuthentication(),],把全部的認證類對象封裝到request裏面了 negotiator=self.get_content_negotiator(), parser_context=parser_context )
get_parsers 獲取解析對象的列表
def get_parsers(self): """ Instantiates and returns the list of parsers that this view can use. """ return [parser() for parser in self.parser_classes]
parser_classes
一樣咱們能夠在settings裏面全局配置,咱們通常使用的就是全局的配置
REST_FRAMEWORK = { #版本 "DEFAULT_VERSIONING_CLASS":"rest_framework.versioning.URLPathVersioning", #解析器 "DEFAULT_PARSER_CLASSES":["rest_framework.parsers.JSONParser","rest_framework.parsers.FormParser"] }