在探索Django的項目,我想首當其衝的肯定是python manage.py runserver
了吧!!runserver肯定是在開發Django最常用到的指令了,每次輸入完後就看他跑一些東西,然後呢~
然後server就run起來了,Django背後到底做了什麼?一行指令就讓server跑起來這是什麼黑魔法!
今天就來探索探索runserver背後的運行過程吧!
開門見山的說,直接上圖
摁~這畫質有夠差(X
讓我把圖拆成兩份來看
清楚多了!
不過可以很明顯地看到他肯定做了很多事,而且我還沒列出全部上圖只是大部分我自己覺得重要的過程而已!!其他可能有點重要的部分我們之後再來深究!
接下來我會一個步驟一個步驟的走我是怎麼把這張圖畫出來的!
首先呢當然就是從指令下手python manage.py runserver
,其中的manage.py不知道大家有沒有點進去看過,當中就是我們第一個探勘地點~
manage.py長這樣
#!/usr/bin/env python
"""Django's command-line utility for administrative tasks."""
import os
import sys
def main():
"""Run administrative tasks."""
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'iron_man001.settings')
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from exc
execute_from_command_line(sys.argv)
# 這邊的sys.argv = [manage.py, runserver]
if __name__ == '__main__':
main()
挺短的也挺好懂的,基本上看變數和function名稱就可以大概知道在做什麼事情了~
那我們繼續跟著execute_from_command_line(sys.argv)
看下去
以下位置在 django.core.management.__init__ 裡面
new 出一個 ManagementUtility()
然後execute()
他,來看看execute()
在做什麼~CommandParser()
是去繼承python lib的argparse.ArgumentParser()
(python argparse是一個專門處理CLI command的內建函式庫,有興趣的可以到官網看著文件手刻玩看看~)
再繼續往下挖
這邊settings.INSTALLED_APPS
其實就會去import settings了,這邊先挖個坑,繼續往下
這邊註解寫的很詳細,不管怎樣都會先啟動autoreloading dev server,因為我們的command class還沒被讀到,command class!看來所有的command都會是class呢~
再繼續挖fetch_command()
後run_from_argv()
這兩個function好像又要做一堆事情了
先看看fetch_command()
會return什麼
最一開始會get_commands()
而此function會把django所有相關的資料夾中有commands字眼的都抓進來
接下來
照上圖所示,把該command的class import進來
到這邊fetch_command()
就告一段落了~
那runserver會import哪個command class呢?而run_from_argv()
又在哪呢?
這一個django.contrib.staticfiles.management.commands.runserver
我挖
他會去繼承這個commanddjango.core.management.commands.runserver.Command
我挖
會發現該command會去繼承django.core.management.base
中的BaseCommand
終於找到你了run_from_argv()
中間有些地方就先跳過,去看最下面的self.execute(*args, **cmd_options)
我挖
我再挖handle()
最後會去觸發run()
而run()
又做了一大堆事情,我們放到明天再繼續~
今天的部分大概就是最上面圖的前半段,大概就照著這樣的感覺下去挖原始碼
回顧一下最一開始的python manage.py runserver
引發了那麼一大串的程式互相作用形成,真的是挺有趣的呢,只不過一些地方要稍微想一下找一下就是了~