1.什么是解析器?
对请求的数据进行解析-请求体进行解析。解析器在你不拿请求体数据时,不会被调用。
安装与使用:(官方文档)
https://www.django-rest-framework.org/
pip install djangorestframework
1 from rest_framewirk.views import APIView 2 class UsersView(APIView): 3 def get(self,request,*args,**kwargs): 4 5 return Response('...') 6 7 def post(self,request,*args,**kwargs): 8 # # application/json 9 # print(request._request.body) # b"xxxxx" decode() json.loads 10 # print(request._request.POST) # 无 11 # 当post 请求的数据格式是application/json的时候, request._request.body有值,而request._request.POST并没有值 12 # 我们要通过 decode + json.loads 来获取数据 13 14 # # www-form-url-encode 15 # print(request._request.body) 16 # print(request._request.POST) 17 # 当post 请求的数据格式是www-form-url-encode的时候,request._request.body和request._request.POST都有值 18 19 20 # 而在我们用rest framework时往往发送的都是json格式的数据,那我们每次都要这么费事的转化吗,答案肯定不是 21 # 可以设置 parser_classes 22 23 from rest_framework.parsers import JSONParser,FormParser 24 class UsersView(APIView): 25 parser_classes = [JSONParser,FormParser] #表示服务端可以解析的数据格式的种类。 26 #如果客户端的Content-Type的值和 application/json 匹配:JSONParser处理数据 27 #如果客户端的Content-Type的值和 application/x-www-form-urlencoded 匹配:FormParser处理数据 28 29 def get(self,request,*args,**kwargs): 30 return Response('...') 31 32 def post(self,request,*args,**kwargs): 33 # request.data 就是 处理转化后的数据 {'name':'xxx','age':'12'} 34 print(request.data) 35 print(request.FILES) 36 print(request.POST) 37 return Response('...') 38 39 # 全局使用: 配置文件 一般都默认使用全局配置 40 REST_FRAMEWORK = { 41 'DEFAULT_PARSER_CLASSES':[ 42 'rest_framework.parsers.JSONParser', 43 'rest_framework.parsers.FormParser', 44 ] 45 }
2.print(request.data)的源码
1 class Request(object): 2 @property 3 def data(self): 4 if not _hasattr(self, '_full_data'): 5 #调用_load_data_and_files方法 6 self._load_data_and_files() 7 return self._full_data 8 9 def _load_data_and_files(self): 10 if not _hasattr(self, '_data'): 11 #调用_parse方法 12 self._data, self._files = self._parse() 13 14 def _parse(self): 15 #调用DefaultContentNegotiation类的select_parser方法,见下面 16 parser = self.negotiator.select_parser(self, self.parsers) # 在封装Request的时候self.parser = 配置的解析类的对象列表 17 #self.negotiator = self._default_negotiator() = api_settings.DEFAULT_CONTENT_NEGOTIATION_CLASS() 18 19 if not parser: 20 #如果返回 None 说明不匹配,抛出异常 21 raise exceptions.UnsupportedMediaType(media_type) 22 23 try: 24 # 匹配成功, 相应的解析类对象调用parse方法 25 parsed = parser.parse(stream, media_type, self.parser_context) 26 27 class DefaultContentNegotiation(BaseContentNegotiation): 28 def select_parser(self, request, parsers): 29 for parser in parsers: 30 # 判断 解析类的对象和 请求的 content_type 是否匹配 31 if media_type_matches(parser.media_type, request.content_type): 32 return parser 33 return None 34 35 36 拿 JSONParser 举例 37 class JSONParser(BaseParser): 38 39 media_type = 'application/json' 40 renderer_class = renderers.JSONRenderer 41 strict = api_settings.STRICT_JSON 42 43 def parse(self, stream, media_type=None, parser_context=None): 44 try: #和我们自己处理是一个原理 45 # 先decode 46 decoded_stream = codecs.getreader(encoding)(stream) 47 parse_constant = json.strict_constant if self.strict else None 48 # 再load 49 return json.load(decoded_stream, parse_constant=parse_constant) 50 except ValueError as exc: 51 raise ParseError('JSON parse error - %s' % six.text_type(exc))