1. 前置面向对象知识点
- 直接访问或利用反射
class Foo(object):
def __init__(self, name, age):
self.name = name
self.age = age
def show(self):
return 123
obj = Foo("小三", 19)
# obj.name
# obj.age
# obj.show()
v1 = getattr(obj, 'show')
print(v1)
- getattr
- 当对象.一个不存在的成员时触发
class Foo(object):
def __init__(self, name, age):
self.name = name
self.age = age
def show(self):
return 123
def __getattr__(self, item):
print("----->", item)
return 999
obj = Foo("小三", 19)
# 不触发 __getattr
# obj.name
# obj.age
# obj.show()
# 触发 __getattr__ (不存在的成员)
# print(obj.xxx)
v2 = getattr(obj, "xxxx")
print(v2)
- getattribute
- 只要执行 对象.xxx都会执行__getattribute__
- 父类object中的__getattribute__的处理机制
- 对象中有值,返回
- 对象中无值,报错
class Foo(object):
def __init__(self, name, age):
self.name = name
self.age = age
def show(self):
return 123
def __getattribute__(self, item):
print("----->", item)
return 999
obj = Foo("小三", 19)
print(obj.name)
print(obj.age)
print(obj.xxx)
- 类分析
class HttpRequest(object):
def __init__(self):
pass
def v1(self):
print("v1")
def v2(self):
print("v2")
class Request(object):
def __init__(self, req, xx):
self._request = req
self.xx = xx
req = HttpRequest()
req.v1()
req.v2()
request = Request(req, 111)
request._request.v1()
request._request.v2()
class HttpRequest(object):
def __init__(self):
pass
def v1(self):
print("v1")
def v2(self):
print("v2")
class Request(object):
def __init__(self, req, xx):
self._request = req
self.xx = xx
# 对象中无的成员,会触发
def __getattr__(self, attr):
# attr="v1"
try:
return getattr(self._request, attr) # self._request.v1
except AttributeError:
return self.__getattribute__(attr)
req = HttpRequest()
request = Request(req, 111)
request.v1()
- request的简单实现原理
class HttpRequest(object):
def __init__(self):
pass
def method(self):
print("v1")
def path_info(self):
print("v2")
class DrfRequest(object):
def __init__(self, req, xx):
self._request = req
self.xx = xx
def __getattr__(self, attr):
try:
return getattr(self._request, attr)
except AttributeError:
return self.__getattribute__(attr)
request = HttpRequest()
request = DrfRequest(request, 123123)
# 普通写法
request._request.method
# 利用__getattr__和__getattribute__
request.method
request.path_info
# 报错
request.uuuu
2. 参数
测试代码
from django.contrib import admin
from django.urls import path, re_path
from api import views
urlpatterns = [
# path('admin/', admin.site.urls),
# path('users/<str:version>/<int:pid>/', views.UserView.as_view()),
# re_path('users/(\w+)/(\d+)/', views.UserView.as_view()),
re_path('users/(?P<version>\w+)/(?P<pid>\d+)/', views.UserView.as_view()),
]
from rest_framework.views import APIView
from rest_framework.response import Response
class UserView(APIView):
def get(self, request, version, pid):
print(version, pid)
print(self.kwargs)
print(self.args)
return Response("...")
3. 源码分析
流程梳理-文字版
注意:下列调用方法的找寻路线遵循先UserView类,后APIView类,最后是View类,就不再详细赘述找寻过程
首先入口是路由中调用UserView类的as_View()方法,找到APIView类的as_view()方法,又调用View类的as_view()方法
View类的as_view()方法调用APIView类的dispatch方法
dispatch()方法调用initialize_request()方法,将django的request传给drf的Request类进行封装,self._request = request,并且定义了__getattr__方法,用于在drf的request中调用原生django的request
此时initialize_request()方法调用完毕,回到dispatch()方法
dispatch()获取请求方法,并调用,将结果一步步返回
源代码分析-精简版
class APIView(View):
def as_view(cls, **initkwargs):
view = super().as_view(**initkwargs)
return csrf_exempt(view)
def initialize_request(self, request, *args, **kwargs):
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
)
def dispatch(self, request, *args, **kwargs):
self.args = args
self.kwargs = kwargs
# request还是django中的request
request = self.initialize_request(request, *args, **kwargs)
# 此时的request时drf的request,request._request就是原生django的request
# request._request.method
# request.method # __getattr__
self.request = request
self.headers = self.default_response_headers
if request.method.lower() in self.http_method_names:
# 获取get/post/put等方法
handler = getattr(self, request.method.lower(),self.http_method_not_allowed)
# 调用get/post等方法(UserView中)
response = handler(request, *args, **kwargs)
self.response = self.finalize_response(request, response, *args, **kwargs)
return self.response
class View:
def as_view(cls, **initkwargs):
def view(request, *args, **kwargs):
return self.dispatch(request, *args, **kwargs)
return view
class Request:
def __init__(self, request, parsers=None, authenticators=None,
negotiator=None, parser_context=None):
self._request = request
def __getattr__(self, attr):
try:
return getattr(self._request, attr)
except AttributeError:
return self.__getattribute__(attr)
class UserView(APIView):
def get(self, request, version, pid):
print(version, pid)
print(self.kwargs)
print(self.args)
return Response("...")
4. request对象
drf中的request其实是对请求的再次封装,其目的就是在原来的request对象基础中再进行封装一些drf中需要用到的值
测试代码
from django.contrib import admin
from django.urls import path, re_path
from api import views
urlpatterns = [
# path('admin/', admin.site.urls),
# path('users/<str:version>/<int:pid>/', views.UserView.as_view()),
# re_path('users/(\w+)/(\d+)/', views.UserView.as_view()),
re_path('users/(?P<version>\w+)/(?P<pid>\d+)/', views.UserView.as_view()),
]
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.request import Request
class UserView(APIView):
def get(self, request, version, pid):
# drf的request对象
print(request.query_params)
print(request.data)
print(request.auth)
print(request.user)
# django的request对象
print(request.GET)
print(request.method)
print(request.path_info)
return Response("...")