别摸我
别摸我
文章目录
  1. Django框架总览
  2. Django运行方式
    1. 1、runserver 方式

Django源码分析(一)--runserver启动过程分析

Django框架总览


Django运行方式

一般运行 Django 项目的方法有两种:

  • 在开发和调试中一般用 runserver 方法, 使用 Django 自己的 Web Server

  • 正式生产环境一般用 uWSGIfastcgi 等协议运行 Django 项目

1、runserver 方式

用法:(./manage.py help runserver查看)

1
2
3
4
5
6
7
8
9
usage: manage.py runserver [-h] [--version] [-v {0,1,2,3}]
[--settings SETTINGS] [--pythonpath PYTHONPATH]
[--traceback] [--no-color] [--ipv6] [--nothreading]
[--noreload] [--nostatic] [--insecure]
[addrport]

python manage.py runserver # default port is 8000
python manage.py runserver 8080
python manage.py runserver 127.0.0.1:8000

查看 manage.py 内容可以发现, 首先

1
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "fadada.settings")

设置了一个环境变量 DJANGO_SETTINGS_MODULE 等于 project.settings, 然后直接执行 django.core.management 中的 execute_from_command_line 方法, 并把命令行输入的参数传进去。

一路看到 ManagementUtilityexecute 方法:

1
2
3
4
5
6
7
8
9
10
11
#django\core\management\__init__.py
class ManagementUtility:
def execute(self):
"""
Given the command-line arguments, figure out which subcommand is being
run, create a parser appropriate to that command, and run it.
"""
...
self.autocomplete()
...
self.fetch_command(subcommand).run_from_argv(self.argv)

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
# django\core\management\base.py
class BaseCommand:
def run_from_argv(self, argv):
...
self.execute(*args, **cmd_options)
...

# django\core\management\commands\runserver.py
class Command(BaseCommand):
def execute(self, *args, **options):
if options['no_color']:
# We rely on the environment because it's currently the only
# way to reach WSGIRequestHandler. This seems an acceptable
# compromise considering `runserver` runs indefinitely.
os.environ["DJANGO_COLORS"] = "nocolor"
super().execute(*args, **options)

# django\core\management\base.py
class BaseCommand:
def execute(self, *args, **options):
...
output = self.handle(*args, **options)
...

# django\contrib\staticfiles\management\commands\runserver.py
class Command(BaseCommand):
def get_handler(self, *args, **options):
"""Return the default WSGI handler for the runner."""
return get_internal_wsgi_application()
def handle(self, *args, **options):
...
self.run(**options)
...

def run(self, **options):
...
self.inner_run(None, **options)

def inner_run(self, *args, **options):
...
handler = self.get_handler(*args, **options)
run(self.addr, int(self.port), handler,
ipv6=self.use_ipv6, threading=threading, server_cls=self.server_cls)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# django\core\servers\basehttp.py
def get_internal_wsgi_application():
...
return get_wsgi_application()

class WSGIRequestHandler(simple_server.WSGIRequestHandler):

def run(addr, port, wsgi_handler, ipv6=False, threading=False, server_cls=WSGIServer):
...
httpd.set_app(wsgi_handler) # 这里的wsgi_hander 是get_handler返回的一个 WSGIHandler 对象
httpd.serve_forever()

# django\core\wsgi.py
def get_wsgi_application():
django.setup(set_prefix=False)
return WSGIHandler()
1
2
3
4
5
6
7
8
9
10
11
# django\core\handlers\wsgi.py
class WSGIHandler(base.BaseHandler):
request_class = WSGIRequest

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.load_middleware()

# django\core\handlers\base.py
class BaseHandler:
...

runserver 命令先解析参数, 后面通过 django.core.servers.basehttp.get_internal_wsgi_application 方法获取 wsgi_handler, 这个方法先根据 settings 中的 WSGI_APPLICATION 来获取 handler, 在创建 project 的时候, Django 会默认创建一个 wsgi.py 文件,而 settings 中的 WSGI_APPLICATION 配置也会默认指向这个文件。看一下这个 wsgi.py 文件,其实它也和上面的逻辑一样,最终调用 get_wsgi_application 实现。

然后根据 ip addressport 生成一个 WSGIServer 对象 httpd,接受用户请求。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def run(addr, port, wsgi_handler, ipv6=False, threading=False, server_cls=WSGIServer):
server_address = (addr, port)
if threading:
httpd_cls = type('WSGIServer', (socketserver.ThreadingMixIn, server_cls), {})
else:
httpd_cls = server_cls
httpd = httpd_cls(server_address, WSGIRequestHandler, ipv6=ipv6)
if threading:
# ThreadingMixIn.daemon_threads indicates how threads will behave on an
# abrupt shutdown; like quitting the server by the user or restarting
# by the auto-reloader. True means the server will not wait for thread
# termination before it quits. This will make auto-reloader faster
# and will prevent the need to kill the server manually if a thread
# isn't terminating correctly.
httpd.daemon_threads = True
httpd.set_app(wsgi_handler)
httpd.serve_forever()

WSGIHandler 会初始化中间件并加载 settings.MIDDLEWARE 中的中间件, 关于中间件的问题下节再讲~

支持一下
扫一扫,支持heaven
  • 微信扫一扫
  • 支付宝扫一扫