Django 源码阅读:url解析
Posted Mr_扛扛
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Django 源码阅读:url解析相关的知识,希望对你有一定的参考价值。
一、写在前面
继上一篇博文,进一步分析Django URL解析过程。通过网上博客的学习以及对于源码阅读所做笔记。
邮箱地址:jpzhang.ht@gmail.com
个人博客:https://jianpengzhang.github.io/
CSDN博客:http://blog.csdn.net/u011521019
二、写在前面
上一篇博文,django.core.servers.basehttp.py run()函数,服务启动最后的动作是httpd.serve_forever,调用的是socketserver.BaseServer.serve_forever方法。该方法采用了selector网络模型进行等待数据。启动服务后服务器进入一个无限循环的状态,poll_interval用来设置循环间隔时间,默认为0.5秒。在这里先简单分析下Python SocketServer.py 源码,上篇博文中这块的介绍没有好好的梳理。在这里进行补充下。
/usr/lib/python2.7/SocketServer.py:BaseServer.serve_forever()
class BaseServer:
timeout = None
def __init__(self, server_address, RequestHandlerClass):
# 初始化,传入构建一个Socket服务器所必需的address以及每个请求到达时的处理类
"""Constructor. May be extended, do not override."""
self.server_address = server_address
# RequestHandlerClass 注册 handle 函数,在finish_request 中实例化,调用用户定义的 handle 函数
self.RequestHandlerClass = RequestHandlerClass
self.__is_shut_down = threading.Event()
self.__shutdown_request = False
def server_activate(self):
"""Called by constructor to activate the server.
May be overridden.
服务器激活,由构造函数调用以激活服务器。可能被重写。
"""
pass
# 装饰器函数,重新启动被eintr中断的系统调用
def _eintr_retry(func, *args):
"""restart a system call interrupted by EINTR"""
while True:
try:
return func(*args)
except (OSError, select.error) as e:
if e.args[0] != errno.EINTR:
raise
def serve_forever(self, poll_interval=0.5):
"""Handle one request at a time until shutdown.
Polls for shutdown every poll_interval seconds. Ignores
self.timeout. If you need to do periodic tasks, do them in
another thread.
"""
self.__is_shut_down.clear()
try:
while not self.__shutdown_request:
# XXX: Consider using another file descriptor or
# connecting to the socket to wake this up instead of
# polling. Polling reduces our responsiveness to a
# shutdown request and wastes cpu at all other times.
# 调用 select 监视请求,处理 EINTR 异常
r, w, e = _eintr_retry(select.select, [self], [], [],
poll_interval)
if self in r:
# 有请求进来
self._handle_request_noblock()
finally:
self.__shutdown_request = False
self.__is_shut_down.set()
… …
SocketServer.py中的 BaseServer 和 BaseRequestHandler
Python为网络编程提高了更高级的封装。SocketServer.py 提供了不少网络服务的类。它们的设计很优雅。Python把网络服务抽象成两个主要的类,一个是Server类,用于处理连接相关的网络操作,另外一个则是RequestHandler类,用于处理数据相关的操作。并且提供两个MixIn 类,用于扩展 Server,实现多进程或多线程。在构建网络服务的时候,Server 和 RequestHandler 并不是分开的,RequestHandler的实例对象在Server 内配合 Server工作。
主要几个Server关系如下:
+------------+
| BaseServer |
+------------+
|
v
+-----------+ +------------------+
| TCPServer |------->| UnixStreamServer |
+-----------+ +------------------+
|
v
+-----------+ +--------------------+
| UDPServer |------->| UnixDatagramServer |
+-----------+ +--------------------+
BaseServer 分析
BaseServer 通过__init__初始化,对外提供serve_forever和 handler_request方法,在这里初始化动作是在django.core.servers.basehttp.py run()函数中httpd = httpd_cls(server_address, WSGIRequestHandler, ipv6=ipv6)
触发,其中httpd_cls是通过type()函数动态加载的WSGIServer类,这里httpd_cls表示:<class 'django.core.servers.basehttp.WSGIServer'>
,继承自:<class 'django.core.servers.basehttp.WSGIServer'>
,socketserver.ThreadingMixIn
。
init 初始化:
def __init__(self, server_address, RequestHandlerClass):
# 初始化,传入构建一个Socket服务器所必需的address以及每个请求到达时的处理类
"""Constructor. May be extended, do not override."""
self.server_address = server_address
# RequestHandlerClass 注册 handle 函数,在finish_request 中实例化,调用用户定义的 handle 函数
self.RequestHandlerClass = RequestHandlerClass
self.__is_shut_down = threading.Event()
self.__shutdown_request = False
__init__源码很简单。主要作用是创建server对象,并初始化server地址和处理请求的class。熟悉socket编程应该很清楚,server_address是一个包含主机和端口的元组。
serve_forever
创建了server对象之后,使用server对象开启一个无限循环。
def serve_forever(self, poll_interval=0.5):
"""Handle one request at a time until shutdown.
Polls for shutdown every poll_interval seconds. Ignores
self.timeout. If you need to do periodic tasks, do them in
another thread.
"""
self.__is_shut_down.clear()
try:
while not self.__shutdown_request:
# XXX: Consider using another file descriptor or
# connecting to the socket to wake this up instead of
# polling. Polling reduces our responsiveness to a
# shutdown request and wastes cpu at all other times.
# 调用 select 监视请求,处理 EINTR 异常
r, w, e = _eintr_retry(select.select, [self], [], [],
poll_interval)
if self in r:
# 有请求进来
self._handle_request_noblock()
finally:
self.__shutdown_request = False
self.__is_shut_down.set()
serve_forever接受一个参数poll_interval,用于表示select轮询的时间。然后进入一个无限循环,调用select方式进行网络IO的监听。
如果select函数返回,表示有IO连接或数据,那么将会调用_handle_request_noblock方法。
_handle_request_noblock
def _handle_request_noblock(self):
"""Handle one request, without blocking.
I assume that select.select has returned that the socket is
readable before this function was called, so there should be
no risk of blocking in get_request().
处理一个请求,不会阻塞。 我假设select.select返回了在调用此函数之前套接字是可读的,因此get_request()中不应存在阻塞的风险。
"""
try:
# 接收请求 accept,get_request 由子类实现,一般为接收请求,返回 socket
request, client_address = self.get_request()
except socket.error:
return
if self.verify_request(request, client_address):
try:
# BaseServer.process_request 中有 BaseRequestHandler 的回调动作,实例化用户定义的 handler, __init__ 中完成对 handle() 的调用
self.process_request(request, client_address)
except:
self.handle_error(request, client_address)
# 关闭连接
self.shutdown_request(request)
else:
self.shutdown_request(request)
_handle_request_noblock方法即开始处理一个请求,并且是非阻塞。该方法通过get_request方法获取连接,具体的实现在其子类。一旦得到了连接,调用verify_request方法验证请求。验证通过,即调用process_request处理请求。如果中途出现错误,则调用handle_error处理错误,以及shutdown_request结束连接。
get_request
在这里,调用的是子类class TCPServer(BaseServer)
中的get_request。TCPServer 继承了BaseServer,初始化的时候,进行了socket套接字的创建。
get_request:
该类最重要的方法就是 get_request。该方法进行返回socket对象的请求连接。
def get_request(self):
"""Get the request and client address from the socket.
May be overridden.
从套接字获取请求和客户端地址。可以覆盖。
"""
return self.socket.accept()
get_request方法是在BaseServer基类中的_handle_request_noblock中调用,从那里里传入套接字对象获取的连接信息。如果是UDPServer,这里获取的就是UDP连接。
此外,TCPServer还提供了一个 fileno 方法,提供给基类的select调用返回文件描述符。
verify_request
def verify_request(self, request, client_address):
"""Verify the request. May be overridden.
Return True if we should proceed with this request.
验证请求。 可以覆盖。如果我们应该继续这个请求,则返回True。
"""
return True
该方法对request进行验证,通常会被子类重写。简单的返回True即可,然后进入process_request方法处理请求。
process_request
在这里调用的是在ThreadingMixIn类定义的process_request函数,并不是BaseServer类中的process_request。
class ThreadingMixIn:
"""Mix-in class to handle each request in a new thread.用于处理新线程中的每个请求的混合类。"""
# Decides how threads will act upon termination of the
# main process
# 决定线程在主进程终止时的操作方式
daemon_threads = False
def process_request_thread(self, request, client_address):
"""Same as in BaseServer but as a thread.
In addition, exception handling is done here.
与BaseServer相同,但这里作为线程。此外,此处完成异常处理。
"""
try:
self.finish_request(request, client_address)
self.shutdown_request(request)
except:
self.handle_error(request, client_address)
self.shutdown_request(request)
def process_request(self, request, client_address):
"""Start a new thread to process the request.启动一个新线程来处理请求"""
t = threading.Thread(target = self.process_request_thread,
args = (request, client_address))
t.daemon = self.daemon_threads
t.start()
process_request方法是mixin的入口,MixIn子类通过重写该方法,进行多线程或多进程的配置。调用finish_request完成请求的处理,同时调用shutdown_request结束请求。
finish_request
def finish_request(self, request, client_address):
"""Finish one request by instantiating RequestHandlerClass.
通过实例化RequestHandlerClass完成一个请求。
"""
self.RequestHandlerClass(request, client_address, self)
finish_request方法将会处理完毕请求。创建RequestHandlerClass对象,并通过RequestHandlerClass做具体的处理。
其中self.RequestHandlerClass(request, client_address, self)
:在_init_()中定义为self.RequestHandlerClass = RequestHandlerClass
。
在这里,RequestHandlerClass
参数是上一博文中,在:
django.core.servers.basehttp.py
run()函数(1)中定义的WSGIRequestHandler类,在(2)中进行初始化,既调用BaseServer中的_init_()。
def run(addr, port, wsgi_handler, ipv6=False, threading=False, server_cls=WSGIServer):
server_address = (addr, port)
if threading:
httpd_cls = type(str('WSGIServer'), (socketserver.ThreadingMixIn, server_cls), ) # (1)这里,动态加载类,这里httpd_cls:<class 'django.core.servers.basehttp.WSGIServer'>,继承自:<class 'django.core.servers.basehttp.WSGIServer'>,socketserver.ThreadingMixIn
else:
httpd_cls = server_cls
httpd = httpd_cls(server_address, WSGIRequestHandler, ipv6=ipv6) #(2)这里,参数WSGIRequestHandler:<class 'django.core.servers.basehttp.WSGIRequestHandler'>
… …
因此,RequestHandlerClass是由django.core.servers.basehttp.py: def run() -> httpd = httpd_cls(server_address, WSGIRequestHandler, ipv6=ipv6)
传递过来的参数WSGIRequestHandler:django.core.servers.basehttp.WSGIRequestHandler。
也就是说当执行self.RequestHandler(request, client_address, self)时等同于执行django.core.servers.basehttp.WSGIRequestHandler(request, client_address, self)
。
WSGIRequestHandler
django.core.servers.basehttp.WSGIRequestHandler(request, client_address, self)
。
在这里,初始化WSGIRequestHandler的时候可以看到并没有__init__()函数,查看继承关系,
django.core.servers.basehttp.WSGIRequestHandler ->
simple_server.WSGIRequestHandler ->
BaseHTTPServer.BaseHTTPRequestHandler ->
SocketServer.StreamRequestHandler ->
SocketServer.BaseRequestHandler
在这里即调用BaseRequestHandler类_init_ 完成对 handle() 的调用。
BaseRequestHandler 分析
所有requestHandler都继承BaseRequestHandler基类。
class BaseRequestHandler:
def __init__(self, request, client_address, server):
self.request = request # 客户端请求对象,<class 'socket._socketobject'>
self.client_address = client_address # 客户端地址,('192.168.31.178', 50029)
self.server = server # 服务端
self.setup() # 调用子类的setup()函数,处理socket连接
try:
self.handle()
finally:
self.finish()
def setup(self):
pass
def handle(self):
pass
def finish(self):
pass
BaseRequestHandler是请求处理程序类的基类,该类会处理每一个请求。
_init_()为每个要处理的请求实例化该类。 初始化对象的时候,设置请求request对象、client_address和server,然后调用setup方法,子类会重写该方法,用于处理socket连接,接下来的将是handler和finish方法。 要实现特定服务,需要做的就是派生一个定义handle()方法的类。所有对请求的处理,都可以重写handler方法。
可以简单的理解为:setup()是处理前的初始化操作,handle()是处理请求,finish()是清理操作。
setup(self)
设置完请求request对象、client_address和server后,接着执行self.setup(),该函数在子类StreamRequestHandler实现。
StreamRequestHandler。它继承了BaseRequestHandler。基类的setup方法和finish方法被它重写,用于通过连接实现缓存文件的读写操作。
class StreamRequestHandler(BaseRequestHandler):
"""
rfile、wfile的默认缓冲区大小。我们默认将rfile设为buffered,否则对于大数据(每个字节的getc()调用)会很慢;我们将wfile设为无缓冲,因为(a)通常在写入()之后,我们想要读取并且需要刷新该行;(b)对未缓冲文件的大写入通常由stdio优化。
"""
# 为流式套接字定义rfile和wfile
rbufsize = -1
wbufsize = 0
# 应用于请求套接字的超时(如果不是None)。
timeout = None
# 如果为True,则禁用此套接字的nagle算法。
# 仅在wbufsize!= 0时使用,以避免小数据包。
disable_nagle_algorithm = False
def setup(self):
self.connection = self.request
if self.timeout is not None:
self.connection.settimeout(self.timeout)
if self.disable_nagle_algorithm:
self.connection.setsockopt(socket.IPPROTO_TCP,
socket.TCP_NODELAY, True)
self.rfile = self.connection.makefile('rb', self.rbufsize) # 一个类似文件的对象,可以用来接收客户端的数据
self.wfile = self.connection.makefile('wb', self.wbufsize) # 一个类似文件的对象,可以向客户端返回数据
def finish(self):
if not self.wfile.closed:
try:
self.wfile.flush()
except socket.error:
# 此处可能发生最终套接字错误,例如本地错误ECONNABORTED。
pass
self.wfile.close()
self.rfile.close()
setup
setup判断了是否使用nagle算法。然后设置对应的连接属性。最重要的就是创建了一个可读(rfile)和一个可写(wfile)的“文件”对象,他们实际上并不是创建了文件,而是封装了读取数据和发送数据的操作,抽象成为对文件的操作。可以理解为 self.rfile 就是读取客户端数据的对象,它有一些方法可以读取数据。self.wfile则是用来发送数据给客户端的对象。后面的操作,客户端数据到来会被写入缓冲区可读,需要向客户端发送数据的时候,只需要向可写的文件中write数据即可。
finish
在finish()中清理了对应的文件对象,同时wfile关闭之前需要刷新,将一些没有向客户端返回数据数据返回掉。
def finish(self):
if not self.wfile.closed:
# wfile关闭之前需要刷新
try:
self.wfile.flush()
except socket.error:
pass
self.wfile.close()
self.rfile.close()
handle()
django.core.servers.basehttp.handle()
handle(),调用子类django.core.servers.basehttp.WSGIRequestHandler
中的handle()函数,主要处理的是HTTP是否保持连接的问题,如果保持连接就持续处理客户请求,否则就结束,最后使用shutdown来关闭socket的功能。
handle_one_request()比较重要语句:
def handle(self):
self.close_connection = True
self.handle_one_request()
while not self.close_connection:
# 连接没有关闭,循环处理每一个请求
self.handle_one_request()
try:
"""
使用shutdown来关闭socket的功能
SHUT_RDWR:关闭读写,即不能使用send/write/recv/read等
SHUT_RD:关闭读,即不能使用read/recv等
SHUT_WR:关闭写功能,即不能使用send/write等
除此之外,还将缓冲区中的内容清空
"""
self.connection.shutdown(socket.SHUT_WR)
except (socket.error, AttributeError):
pass
handle_one_request()
def handle_one_request(self):
"""Copy of WSGIRequestHandler.handle() but with different ServerHandler
WSGIRequestHandler.handle()的副本,但具有不同的ServerHandler
"""
# 读取第一行raw_requestline,一般格式应该是:COMMAND PATH VERSION\\r\\n;解析请求。这里:'GET /i18n/js/horizon+openstack_dashboard/ HTTP/1.1\\r\\n'
self.raw_requestline = self.rfile.readline(65537)
if len(self.raw_requestline) > 65536:
# 如果解析的请求地址长度大于65536个字节,发送和记录一个414错误回复给client。
self.requestline = ''
self.request_version = ''
self.command = ''
self.send_error(414)
return
# 解析请求(内部)。请求应存储在self.raw_requestline中; 结果在self.command,self.path,self.request_version和self.headers中。
# 返回True表示成功,False表示失败; 失败时,会发回错误。
if not self.parse_request():
return
# 初始化一个服务器处理程序,初始化动作在父类中实现
# ServerHandler() ->
# django.core.servers.basehttp.ServerHandler()->
# wsgiref.simple_server.ServerHandler() ->
# wsgiref.handlers.SimpleHandler().__init__()
# python重定向sys.stdin、sys.stdout和sys.stderr:标准输入、标准输出和错误输出
# handler:<django.core.servers.basehttp.ServerHandler object at 0x7fca4bdc64d0>
handler = ServerHandler(
self.rfile, self.wfile, self.get_stderr(), self.get_environ()
)
# self:<django.core.servers.basehttp.WSGIRequestHandler object at 0x7fee45763550>
handler.request_handler = self # backpointer for logging & connection closing 用于记录和连接关闭的backpointer
handler.run(self.server.get_app())
其中,self.parse_request(),既调用父类中的BaseHTTPServer.BaseHTTPRequestHandler.parse_request
(),解析请求(内部)。需要解析的请求存储在self.raw_requestline中; 结果在self.command,self.path,self.request_version和self.headers中。返回True表示成功,False表示失败; 失败时,会发回错误。
command:是一个(区分大小写)关键字,如GET或POST。
path:是一个包含请求的路径信息的字符串。应该是字符串“HTTP / 1.0”或“HTTP / 1.1”。使用URL编码方案进行编码(使用%xx表示带有十六进制代码xx的ASCII字符。
request_version:包括请求的HTTP协议版本号的字符串,样例:‘HTTP/1.0’。
headers:headers是包含头信息的mimetools.Message(或派生类)的实例;
HTTP 请求(request)
http 请求分为三个部分:
1. 第一行:请求类型、地址和版本号
2. 头部信息:HTTP header
3. 数据部分
标准的 HTTP 请求是:
GET / HTTP/1.1
Host: cizixs.com
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:42.0) Gecko/20100101 Firefox/42.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: keep-alive
If-Modified-Since: Thu, 25 Feb 2016 16:00:57 GMT
Cache-Control: max-age=0
标准的 HTTP 响应头部:
HTTP/1.1 304 Not Modified
Server: GitHub.com
Date: Thu, 24 Mar 2016 06:21:25 GMT
Last-Modified: Thu, 25 Feb 2016 16:00:57 GMT
access-control-allow-origin: *
Expires: Thu, 24 Mar 2016 06:31:25 GMT
Cache-Control: max-age=600
X-GitHub-Request-Id: 3AF60A59:7CE3:1C889201:56F38765
data...
parse_request()
def parse_request(self)
self.command = None # set in case of error on the first line
# 默认请求版本。这只会影响响应,直到请求行被解析为止,因此它主要决定客户端在发送请求格式错误时返回什么。大多数web服务器默认为HTTP 0.9,即不发送状态行。
self.request_version = version = self.default_request_version
# 关闭连接设置为真
self.close_connection = 1
# 原始请求行
requestline = self.raw_requestline
# 删除 requestline 字符串末尾的指定字符,这里表示换行
requestline = requestline.rstrip('\\r\\n')
self.requestline = requestline
# 默认一空格分割请求行
words = requestline.split()
if len(words) == 3:
command, path, version = words
if version[:5] != 'HTTP/':
# 如果请求版本不是HTTP/开头,则返回400
self.send_error(400, "Bad request version (%r)" % version)
return False
try:
# 例如version=HTTP/1.1,则返回1.1
base_version_number = version.split('/', 1)[1]
# 返回['1', '1']
version_number = base_version_number.split(".")
# RFC 2145 3.1节规定只能有一个'.' 和主要和次要数字必须被视为单独的整数;
if len(version_number) != 2:
# 如果包含版本好的数字少于两个则抛出异常
raise ValueError
# 类型转换(1, 1)
version_number = int(version_number[0]), int(version_number[1])
except (ValueError, IndexError):
self.send_error(400, "Bad request version (%r)" % version)
return False
# 如果版本好大于等于(1, 1),以及支持的HTTP协议版本大于等于"HTTP/1.1",则表示请求的版本号正确,关闭连接设置为假。
if version_number >= (1, 1) and self.protocol_version >= "HTTP/1.1":
self.close_connection = 0
if version_number >= (2, 0):
self.send_error(505,
"Invalid HTTP Version (%s)" % base_version_number)
return False
elif len(words) == 2:
# 请求第一行2个,即“请求类型”、“地址”和“版本号”中缺少一个,则返回400错误。
command, path = words
self.close_connection = 1
if command != 'GET':
self.send_error(400,
"Bad HTTP/0.9 request type (%r)" % command)
return False
elif not words:
return False
else:
self.send_error(400, "Bad request syntax (%r)" % requestline)
return False
# 如果http请求第一行为:GET / HTTP/1.1,则:self.command=GET, self.path=/, self.request_version=HTTP/1.1
self.command, self.path, self.request_version = command, path, version
# 检查标题并查找连接指令
self.headers = self.MessageClass(self.rfile, 0)
# 请求头中查找“Connection: keep-alive”
conntype = self.headers.get('Connection', "")
if conntype.lower() == 'close':
# 关闭请求连接
self.close_connection = 1
elif (conntype.lower() == 'keep-alive' and
self.protocol_version >= "HTTP/1.1"):
# 保持请求连接
self.close_connection = 0
return True
handle_one_request()最后执行到handler.run(self.server.get_app())
这里包含两个动作:self.server.get_app()、handler.run()
self.server.get_app(),/usr/lib/python2.7/wsgiref/simple_server.py:WSGIServer().get_app()
def get_app(self):
# <django.contrib.staticfiles.handlers.StaticFilesHandler object at 0x7fee45834c10>
return self.application
返回一个StaticFilesHandler类对象,继承WSGIHandler,它的目的是为了判断每个请求,如果是常规的url请求则直接分配到某个view中去执行,如果是静态文件规则那么将不会找view而是响应这个文件。
这里请求的地址为:/i18n/js/horizon+openstack_dashboard/看上去是一个静态文件。
handler.run(),/usr/lib/python2.7/wsgiref/handlers.py(76):BaseHandler.run()
def run(self, application):
"""Invoke the application调用应用程序"""
try:
# 为一个请求设置环境,包括输入、错误输出。
self.setup_environ()
# 调用:/usr/local/lib/python2.7/dist-packages/django/contrib/staticfiles/handlers.py(62)__call__()
self.result = application(self.environ, self.start_response)
# 发送任何可迭代数据,然后关闭self和iterable
self.finish_response()
except:
try:
self.handle_error()
except:
# If we get an error handling an error, just give up already!
self.close()
raise # ...and let the actual server figure it out.
self.result = application(self.environ, self.start_response) ->
/usr/local/lib/python2.7/dist-packages/django/contrib/staticfiles/handlers.py(62)StaticFilesHandler(WSGIHandler)
.call() ->
/usr/local/lib/python2.7/dist-packages/django/core/handlers/wsgi.py(153)WSGIHandler(base.BaseHandler).call()
def __call__(self, environ, start_response):
set_script_prefix(get_script_name(environ))
signals.request_started.send(sender=self.__class__, environ=environ)# 向接受通知的注册者发送通知
request = self.request_class(environ)# 调用WSGIRequest实例化请求
response = self.get_response(request) # 调用处理方法处理request,返回给定HttpRequest的HttpResponse对象
response._handler_class = self.__class__# 设置_handler_class 为当前处理的类
status = '%d %s' % (response.status_code, response.reason_phrase)# 相应结果的状态码和对应描述
# 获取响应的响应头部信息,获取响应的cookie信息
response_headers = [
*response.items(),
*(('Set-Cookie', c.output(header='')) for c in response.cookies.values()),
]
start_response(status, response_headers)# 设置响应的响应头部信息
if getattr(response, 'file_to_stream', None) is not None and environ.get('wsgi.file_wrapper'):# 判断响应中是否有文件传输
response = environ['wsgi.file_wrapper'](response.file_to_stream)
return response# 返回处理结果
调用处理方法处理request,返回给定HttpRequest的HttpResponse对象。
def get_response(self, request):
"""Return an HttpResponse object for the given HttpRequest.返回给定HttpRequest的HttpResponse对象。"""
# Setup default url resolver for this thread为此线程设置默认URL解析程序
set_urlconf(settings.ROOT_URLCONF)# 设置url配置
# 调用settings.MIDDLEWARE中配置的中间件进行处理,
response = self._middleware_chain(request)
response._closable_objects.append(request)
if response.status_code >= 400:
log_response(
'%s: %s', response.reason_phrase, request.path,
response=response,
request=request,
)
return response
至此,简单的分析完成,后续随着自己的理解将进一步补充说明。
以上是关于Django 源码阅读:url解析的主要内容,如果未能解决你的问题,请参考以下文章