启动轻量级 Django

Django 2020-04-19 3546 字 906 浏览 点赞

起步

相比 fastapi、flask 等 http 框架,django 一直被 python 程序员认为“重”。“重”有很多理解方式,我至少认为它不是在指责 django 大而全——由于自己多才多艺而被嫌弃,django 岂不是很冤?!所以我理解的、普遍意义的“重”是:django 总要给我提供我不需要的东西

在我看来,django-admin startprojectdjango-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》


本文由 Guan 创作,采用 知识共享署名 3.0,可自由转载、引用,但需署名作者且注明文章出处。

还不快抢沙发

添加新评论