Jiang's blog

DRF源码解析1--APIView对request的重新封装

Word count: 458Reading time: 2 min
2020/02/19 Share

截取APIView

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
@classmethod
class APIView(View):
def as_view(cls, **initkwargs):
if isinstance(getattr(cls, 'queryset', None), models.query.QuerySet):
def force_evaluation():
raise RuntimeError(
'Do not evaluate the `.queryset` attribute directly, '
'as the result will be cached and reused between requests. '
'Use `.all()` or call `.get_queryset()` instead.'
)
cls.queryset._fetch_all = force_evaluation
# 继承了django中View类的的as_view()方法,然后重写了dispatch方法
view = super().as_view(**initkwargs)
view.cls = cls
view.initkwargs = initkwargs

return csrf_exempt(view)


def dispatch(self, request, *args, **kwargs):
self.args = args
self.kwargs = kwargs
# 在传入request是,apiview对request进行了一次包装
request = self.initialize_request(request, *args, **kwargs)
# 此时self.request是initialize_request方法返回的Request
self.request = request
self.headers = self.default_response_headers # deprecate?

try:
# 相比于View类的dispatch方法,Apiview在这里进行了一次初始化的方法
self.initial(request, *args, **kwargs)

# Get the appropriate handler method
if request.method.lower() in self.http_method_names:
handler = getattr(self, request.method.lower(),
self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed

response = handler(request, *args, **kwargs)

except Exception as exc:
response = self.handle_exception(exc)

self.response = self.finalize_response(request, response, *args, **kwargs)
return self.response

进入self.initalize_request()

1
2
3
4
5
6
7
8
9
10
def initialize_request(self, request, *args, **kwargs):
parser_context = self.get_parser_context(request)
# 可以看到, request已经被封装成Request返回,而request则被封装成Request的一个属性
return Request(
request,
parsers=self.get_parsers(),
authenticators=self.get_authenticators(),
negotiator=self.get_content_negotiator(),
parser_context=parser_context
)

截取Ruquest

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Request:
def __init__(self, request, parsers=None, authenticators=None,
negotiator=None, parser_context=None):
assert isinstance(request, HttpRequest), (
'The `request` argument must be an instance of '
'`django.http.HttpRequest`, not `{}.{}`.'
.format(request.__class__.__module__, request.__class__.__name__)
)
# request被封装了私有属性
self._request = request
@property
def content_type(self):
meta = self._request.META
# 封装了content_type方法获取传输类型
return meta.get('CONTENT_TYPE', meta.get('HTTP_CONTENT_TYPE', ''))

@property
def query_params(self):
"""
More semantically correct name for request.GET.
"""
# django的view中的request.Get属性封装成了query_params属性
return self._request.GET

@property
def data(self):
if not _hasattr(self, '_full_data'):
self._load_data_and_files()
# django的view中的request.Post属性封装成了data属性
return self._full_data

我们可以看出~CBV在内部做了一个分发,本质和FBV是一样的。

以后做接口开发的时候,就要用CBV,学习了restful规范,现在就很容易理解我们为什么用CBV了。

CATALOG
  1. 1. 截取APIView
  2. 2. 进入self.initalize_request()
  3. 3. 截取Ruquest