前言

在探索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引發了那麼一大串的程式互相作用形成,真的是挺有趣的呢,只不過一些地方要稍微想一下找一下就是了~