A parser action:
Processing the request body content request content-type header parser according to the corresponding selected.
There application / json, x-www-form-urlencoded, form-data format
urlencoded: format body member is: name = & LQZ Age = 18 is & wife = liuyifei
FormData: file format of the data portion with the body portion being formed with a distinction
json format: json format in the body is the body
Two global use a parser:
In the settings.py
REST_FRAMEWORK = { 'DEFAULT_PARSER_CLASSES':[ 'rest_framework.parsers.JSONParser'
'rest_framework.parsers.FormParser'
'rest_framework.parsers.MultiPartParser' ] }
View layer:
from rest_framework.views Import APIView from rest_framework.response Import the Response class the TestView (APIView): DEF POST (Self, Request, * args, ** : kwargs) Print (request.content_type) # JSONParser value acquisition request and using the corresponding processing Print (request.data) # file application / time x-www-form-urlencoded or multipart / form-data, request.POST have value in Print (of request.POST) Print (request.FILES) return the Response ( ' the POST request, response content ' ) DEFPUT (Self, Request, * args, ** kwargs): return the Response ( ' the PUT request, response content ' )
Use a parser three parts:
Only the first request body processing request content-type application / json as the
from rest_framework.views Import APIView from rest_framework.response Import the Response from rest_framework.request Import the Request from rest_framework.parsers Import JSONParser class the TestView (APIView): parser_classes = [JSONParser,] DEF POST (Self, Request, * args, ** kwargs) : Print (request.content_type) # acquires the requested value, and using the corresponding processing JSONParser Print (request.data) # when the application / x-www-form- urlencoded or multipart / form-data, request.POST only in value Print (of request.POST) Print (request.FILES) return the Response ( ' the POST request, response content ' ) DEF PUT (Self, Request, * args, ** kwargs): return the Response ( ' the PUT request, response content ' )
Request header request body content-type of application / x-www-form-urlencoded of
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)
Request header content-type of multipart / form-data of the request body
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)
upload files:
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, ]
At the same time more Parser
When using multiple parser, rest framework according to the request is compared to an automatic content-type header, and using a corresponding parser
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)
Four source code analysis:
1 when calling request.data, before parsing, thus starting the @Property DEF the Data (Self): IF not _hasattr (Self, ' _full_data ' ): self._load_data_and_files () return self._full_data 2 View self._load_data_and_files () method ----> self._data, self._files = self._parse () DEF _parse (Self): # the value requested by the user in advance of content_type MEDIA_TYPE = self.content_type # self.parsers is user configurable parser_classes = [FileUploadParser , FormParser] # Self in there content_type, passed into this function parser =self.negotiator.select_parser (Self, self.parsers) 3 View self.negotiator.select_parser (Self, self.parsers) DEF select_parser (Self, Request, parsers): # with over media_type and request.content_type comparison, the parser to return , then calls the parser analysis method # each resolver has media_type = 'multipart / form-data ' attribute for parser in parsers: IF media_type_matches (parser.media_type, request.content_type): return parser return None . 4 eventually calls parser the analytical method to resolve 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] 3self.parser_classes start to find the class itself, can not find the parent to find i.e. APIVIew in parser_classes = api_settings.DEFAULT_PARSER_CLASSES . 4 api_settings is an object, the object was to find DEFAULT_PARSER_CLASSES properties not found, the method will be to getattr DEF __getattr__ (Self, attr): IF attr Not in self.defaults: The raise AttributeError ( " Invalid Setting the API: '% S' " % attr) the try : # call self.user_settings method returns a dictionary, the dictionary then take attributes attr Val = self.user_settings [attr] the except KeyError: # Fall the Back to Defaults Val = self.defaults [attr] # Coerce Import strings classes INTO IF attr in self.import_strings: Val = perform_import (Val, attr) # Cache the Result at The self._cached_attrs.add (attr) setattr (Self, attr, Val) return Val 5 user_settings method, reflected by setting the configuration file to find REST_FRAMEWORK property, can not find, return empty dictionary the @Property DEF user_settings (Self): IF not hasattr (Self, ' _user_settings ' ): self._user_settings = getattr(settings, 'REST_FRAMEWORK', {}) return self._user_settings
Source process:
- When the call request.data to perform analytical method ---- "Select a parser object depending on the encoding pass over, call the parser object parser complete analytical method