DRF中dir(request)无法列出build_absolute_uri方法疑问
原因说明
这个现象是DRF的Request包装逻辑、以及Python内置函数dir()和hasattr()的行为差异共同导致的:
- DRF视图中通过
self.request拿到的对象不是Django原生的HttpRequest实例,是DRF封装的rest_framework.request.Request包装对象,原生Django请求被存放在该对象的_request属性上。 - DRF的Request类本身没有定义
build_absolute_uri方法,它通过重写__getattr__魔术方法实现透明转发:所有访问Request自身不存在的属性的操作,都会自动转发到内部持有的原生_request对象上读取对应属性。简化的源码逻辑如下:
def __getattr__(self, attr): try: return getattr(self._request, attr) except AttributeError: return self.__getattribute__(attr)
- 两个内置函数的行为差异是造成该现象的直接原因:
dir()默认只会枚举对象所属类及所有父类明确定义的属性、方法,以及对象实例__dict__中存储的实例属性,不会主动触发__getattr__探测动态转发的属性。DRF的Request类没有重写__dir__方法把原生请求的属性合并到枚举结果中,因此build_absolute_uri不会出现在dir(request)的返回值里。hasattr()的判断逻辑本质是尝试执行getattr(对象, 属性名),只要调用过程不抛出AttributeError就返回真值。访问request.build_absolute_uri时会触发__getattr__的转发逻辑,成功从_request上拿到对应的方法,因此hasattr(request, 'build_absolute_uri')会返回True。
补充:如果代理类想要让
dir()正确列出被代理对象的属性,需要手动重写__dir__方法,将被代理对象的dir()结果合并到自身的返回列表中,DRF目前没有为Request类实现这个逻辑。
内容的提问来源于stack exchange,提问作者wgf4242
相关产品推荐
相关产品推荐

