啓動輕量級 Django
起步
相比 fastapi、flask 等 http 框架,django 一直被 python 程序員認爲**“重”**。“重”有很多理解方式,我至少認爲它不是在指責 django 大而全——由於自己多才多藝而被嫌棄,django 豈不是很冤?!所以我理解的、普遍意義的“重”是:django 總要給我提供我不需要的東西。
在我看來,django-admin startproject
,django-admin startapp
絕對是萬惡之源。命令末尾一回車,我需要的不需要的都來了,項目的目錄結構也被死死釘住。所以長期以來我對 django 絕無任何好感。直到一次在推特上表達心聲,有個大佬對我的言論充滿鄙夷,一來二去的交鋒,最後被他推薦去看《Lightweight Django》。
我一直以來認爲用 django 寫 demo 是挺煩人的,但《Lightweight Django》的作者卻說:不用麻煩了。
如果是 flask
flask 長期以來作爲 django 的競爭對手,並以“輕”著稱,那麼先來看看 flask 如何啓動一個 web 服務。
from flask import Flask
app = Flask(__name__)
@app.route("/")
def index():
return "hello world"
if __name__ == "__main__":
app.run(host="127.0.0.1", port=8000, debug=True)
很簡潔是不是?但這只是“縮寫”而已。一旦我們要寫一個正常一點的項目,就算是規模小一些,用“縮寫”就不夠用了。比方說響應頭的 header 設置,比方說路由的模塊劃分。所以實際項目中,flask 的代碼組織結構大概率呈現如下方式:
import os
# 環境變量
debug = os.environ.get("debug", "on") == "on"
from flask import Flask, make_response
app = Flask(__name__)
# 配置信息
app.config.update(
debug=debug,
)
# 視圖函數
def index():
response = make_response("hello world")
return response
# 註冊路由
app.add_url_rule("/", None, index)
if __name__ == "__main__":
# 啓動程序
app.run(host="127.0.0.1", port=8000)
(註冊路由不再用裝飾器,僅僅是我個人愛好而已)
也就是說,一個 http 服務至少是需要配置信息,視圖函數,註冊路由三部分;爲了能跟 uwsgi 通信,我們還需要 application,好巧不巧,app = Flask(__name__)
語句中的 app 就是那個我們要的 application;最後是啓動服務的 app.run()
。
請記住這個結構,接下來我們就用 django 來實現。
輕量級 django
首先來完成視圖函數,這稍微簡單些:
from django.http import HttpResponse
def index(request):
response = HttpResponse("hello world")
return response
與 flask 稍稍不同,django 要求視圖函數默認接收一個 request 參數。
接着是路由。django 中,路由的“註冊”方式是靜態的,因爲它不是去註冊,而是以配置的方式添加路由:
from django.conf.urls import url
# urlpatterns 是默認變量
urlpatterns = (
url("^$", index),
)
但是現在對 django 來說,它還找不到路由。django 是自己去註冊路由,而你需要告訴它路由文件在哪兒。**“告訴”**這個動作需要在配置信息里弄。所以正好把 django 的配置信息方式說了。
import os
# 環境變量
debug = os.environ.get("debug", "on") == "on"
from django.conf import settings
settings.configure(
DEBUG=debug,
ROOT_URLCONF=__name__, # 告訴 django, 配置路由的文件在哪兒
)
現在完成了配置信息,視圖函數,註冊路由三部分,我們還需要通信的 application。
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()
最後是啓動服務。你有兩種方式,一種是選擇python xxx.py runserver
,另一種是python xxx.py
。爲了對標 flask,這裏就選擇實現後者:
from django.core.management import execute_from_command_line
execute_from_command_line([__name__, "runserver"])
事實上,我們已經完成了一個輕量級的 django http 服務。完整代碼如下:
import os
from django.http import HttpResponse
from django.conf.urls import url
from django.conf import settings
from django.core.wsgi import get_wsgi_application
# 環境變量
debug = os.environ.get("debug", "on") == "on"
settings.configure(
DEBUG=debug,
ROOT_URLCONF=__name__,
)
# 視圖函數
def index(request):
response = HttpResponse("hello world")
return response
# 註冊路由
urlpatterns = (
url("^$", index),
)
application = get_wsgi_application()
if __name__ == "__main__":
# 啓動程序
from django.core.management import execute_from_command_line
execute_from_command_line([__name__, "runserver"])
總結
認真說起來,輕量級的 django 還是比 flask 麻煩一點點,尤其導包太多(不失尷尬的微笑)。但通過學習啓動輕量級 django,大致明白了 django-admin startproject
生成的內容都有什麼用,也可以自己掌握代碼的目錄結構啦,以後就不會糊里糊塗覺得 django “重” 了。
參考
- 《Lightweight Django - The World’s Smallest Django Project》