DRF-解析器组件源码解析

解析器组件源码解析

解析器组件源码解析
1 执行request.data  开始找重装的request中的data方法
2     在dispatch找到重装的request
    def dispatch(self, request, *args, **kwargs):
        request = self.initialize_request(request, *args, **kwargs)
***这里开始找data
3 在initialize_request中找到实例request的类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(),
            negotiator=self.get_content_negotiator(),
            parser_context=parser_context
        )
    得到类对象Request(),注意parsers=self.get_parsers()后面会回来找
4 Request()中找到data方法
5 在data方法中--关注返回值
    @property
    def data(self):
        if not _hasattr(self, ‘_full_data‘):
            self._load_data_and_files()
        return self._full_data
    由于返回值默认:self._full_data = Empty
    所以self._load_data_and_files()应该对_full_data进行复制了
6 从_load_data_and_files()找到_full_data
        def _load_data_and_files(self):

            if not _hasattr(self, ‘_data‘):
                self._data, self._files = self._parse()
                if self._files:
                    self._full_data = self._data.copy()
                    self._full_data.update(self._files)
                else:
                    self._full_data = self._data
    这里我们把self._parse()的结果分别复制给了self._data, self._files,且都放在了_full_data中,接下来观察self._parse()都给了什么值
7 _parse()
    def _parse():
        parser = self.negotiator.select_parser(self, self.parsers)
        parsed = parser.parse(stream, media_type, self.parser_context)
        empty_files = MultiValueDict()
        return (parsed, empty_files)
    parsed通过parser获取,而传入的参数中的self.parsers,就是我们初始化Request()中传入的参数parsers=self.get_parsers()

// *****这里开始开始和parser_classes我们的设置解析数据类型设置相关了
8 我们回到步骤3找到parsers=self.get_parsers()
9 在get_parsers()中
    return [parser() for parser in self.parser_classes]
    得到从self.parser_classes中循环的列表
// *****选择从调用的视图类中获取parser_classes,没有从APIView中获取parser_classes
10 在APIView中获取到parser_classes
    parser_classes = api_settings.DEFAULT_PARSER_CLASSES
11 从api_settings查找DEFAULT_PARSER_CLASSES方法或属性
    api_settings = APISettings(None, DEFAULTS, IMPORT_STRINGS)
    @property
    def user_settings(self):
        if not hasattr(self, ‘_user_settings‘):
            self._user_settings = getattr(settings, ‘REST_FRAMEWORK‘, {})
        return self._user_settings
    class APISettings():
        def __init__(defaults=None):
            self.defaults = defaults or DEFAULTS
            # 这里将DEFAULTS字典放在实例对象中,
        def __getattr__(self, attr):
            if attr not in self.defaults:
                raise AttributeError("Invalid API setting: ‘%s‘" % attr)

            try:
                # Check if present in user settings
                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
    self.defaults = defaults or DEFAULTS --》这里将DEFAULTS字典放在实例对象中,我们发现DEFAULT_PARSER_CLASSES
    就在字典中
    由于没有DEFAULT_PARSER_CLASSES方法,我们执行__getattr__方法
        1***** val = self.user_settings[attr]优先从配置中找有没有配置的路由解析方法,如果没配置
        2***** val = self.defaults[attr]从实例化对象的内存空间中找方法
        3 val = perform_import(val, attr)将‘rest_framework.parsers.JSONParser‘转化成JSONParser

解析器顺序

  当前访问视图类下------------》全局settings---------》默认default

使用

# 设置全局解析方式
REST_FRAMEWORK={
‘DEFAULT_PARSER_CLASSES‘: (
        ‘rest_framework.parsers.JSONParser‘,
        ‘rest_framework.parsers.FormParser‘,
        ‘rest_framework.parsers.MultiPartParser‘
    ),
}
# 当前访问视图类下设置解析方式
from rest_framework.parsers import JSONParser
from rest_framework.views import APIView

class LoginView(APIView):
    parser_classes = [JSONParser]
    def get(self,request):
        print(‘get‘)
        return render(request,‘login.html‘)
    def post(self,request):
        print(‘body‘,request.body)
        print(request.data)
        print(‘data‘,request.data)
        # print(‘POST‘, request.POST)
        return HttpResponse(‘OK‘)
# 默认使用的解析方式
class APIView(View):
    parser_classes = api_settings.DEFAULT_PARSER_CLASSES

原文地址:https://www.cnblogs.com/benson321/p/9670088.html

时间: 2024-12-13 19:08:25

DRF-解析器组件源码解析的相关文章

Spring 源码解析之HandlerAdapter源码解析(二)

Spring 源码解析之HandlerAdapter源码解析(二) 前言 看这篇之前需要有Spring 源码解析之HandlerMapping源码解析(一)这篇的基础,这篇主要是把请求流程中的调用controller流程单独拿出来了 解决上篇文章遗留的问题 getHandler(processedRequest) 这个方法是如何查找到对应处理的HandlerExecutionChain和HandlerMapping的,比如说静态资源的处理和请求的处理肯定是不同的HandlerMapping ge

Spring 源码解析之DispatcherServlet源码解析(五)

Spring 源码解析之DispatcherServlet源码解析(五) 前言 本文需要有前四篇文章的基础,才能够清晰易懂,有兴趣可以先看看详细的流程,这篇文章可以说是第一篇文章,也可以说是前四篇文章的的汇总,Spring的整个请求流程都是围绕着DispatcherServlet进行的 类结构图 根据类的结构来说DispatcherServlet本身也是继承了HttpServlet的,所有的请求都是根据这一个Servlet来进行转发的,同时解释了为什么需要在web.xml进行如下配置,因为Spr

Spring 源码解析之ViewResolver源码解析(四)

Spring 源码解析之ViewResolver源码解析(四) 1 ViewResolver类功能解析 1.1 ViewResolver Interface to be implemented by objects that can resolve views by name. View state doesn't change during the running of the application, so implementations are free to cache views. I

AQS源码解析(一)-AtomicBoolean源码解析

基本类: AtomicInteger AtomicLong AtomicBoolean 数组类型: AtomicIntegerArray AtomicLongArray AtomicReferenceArray 介绍 由于在多线程条件下,如果对共享变量修改容易造成数据不一致的情况,所以对于共享变量需要保证线程安全有有如下几种方式: 使用lock或者synchronized进行同步共享变量 使用CAS方法来保证修改变量为原子性操作 该类为后者,基于CAS方式修改具有原子性. 实现原理 将boole

【Java源码解析】-- HashMap源码解析

目录 源码解析 1.构造方法 无参构造方法 int型参数的构造方法 int,float两个参数的构造方法 hsah方法 2.添加元素(put()方法) 3.扩容方法(resize()方法) 4.获取元素(get()方法) 5.移除元素(remove()) 6.树化(treeifyBin()) 关于HashMap常见的问题 1.为什么容量始终是2的幂次? 3.既然红黑树那么好,为啥hashmap不直接采用红黑树,而是当大于等于8个的时候才转换红黑树? 4.JDK1.7 扩容死锁产生原因 5.JDK

MapReduce之RecordReader组件源码解析及实例

简述 无论我们以怎样的方式从分片中读取一条记录,每读取一条记录都会调用RecordReader类: 系统默认的RecordReader是LineRecordReader,TextInputFormat: LineRecordReader是用每行的偏移量作为map的key,每行的内容作为map的value: 而SequenceFileInputFormat的RecordReader是SequenceFileRecordReader: 应用场景:自定义读取每一条记录的方式:自定义读入key的类型,如

JAVA常用集合源码解析系列-ArrayList源码解析(基于JDK8)

文章系作者原创,如有转载请注明出处,如有雷同,那就雷同吧~(who care!) 一.写在前面 这是源码分析计划的第一篇,博主准备把一些常用的集合源码过一遍,比如:ArrayList.HashMap及其对应的线程安全实现,此文章作为自己相关学习的一个小结,记录学习成果的同时,也希望对有缘的朋友提供些许帮助. 当然,能力所限,难免有纰漏,希望发现的朋友能够予以指出,不胜感激,以免误导了大家! 二.稳扎稳打过源码 首先,是源码内部的成员变量定义以及构造方法: 1 /** 2 * Default in

源码解析之AQS源码解析

要理解Lock首先要理解AQS,而要理解并发类最好的方法是先理解其并发控制量不同值得含义以及该类运作流程,然后配合一步步看源码.该类有一个重要的控制量是WaitStates. /** waitStatus value to indicate thread has cancelled */ static final int CANCELLED = 1; //该节点被取消了 /** waitStatus value to indicate successor's thread needs unpar

spark内存管理器--MemoryManager源码解析

MemoryManager内存管理器 内存管理器可以说是spark内核中最重要的基础模块之一,shuffle时的排序,rdd缓存,展开内存,广播变量,Task运行结果的存储等等,凡是需要使用内存的地方都需要向内存管理器定额申请.我认为内存管理器的主要作用是为了尽可能减小内存溢出的同时提高内存利用率.旧版本的spark的内存管理是静态内存管理器StaticMemoryManager,而新版本(应该是从1.6之后吧,记不清了)则改成了统一内存管理器UnifiedMemoryManager,同一内存管