概要
Djangoで開発しててWSGI(Web Server Gateway Interface)ってたまに聞くけどよくわかってなかったんで調べてみたら、(あれ、これってひょっとしてpythonで直接叩ける?)とふと思ったんで、検証してみました。
まずWSGIの概要
WSGIの詳細な仕様は各々調べてもらうとして、apache+djangoをWSGIで動かしたとして、大まかに以下の図のような関係になっています。
図にあるようにapacheとdjangoがやり取りするインターフェースの規格がWSGIです。
django側の入り口となるのはwsgi.pyファイルで、そのファイル内に記述されているcallableなエントリポイント(ここではapplication)をapacheが呼び出すことでやり取りします。
と書くと分かりづらいかもしれまんせんが、要は、apacheからapplication関数を呼び出して、その結果をブラウザとかに返すというような感じです。
冒頭の疑問
WSGIの利点として、WSGIの仕様に対応していれば、呼び出し側(apacheとか)やWebアプリ側(djangoとか)が何であっても正常に動作する、というのがあります。
では、以下の場合でも動作するのでは?と考えました。
WSGIの仕様さえ守っていれば何でもいいんだから、呼び出し側はpythonスクリプトにしてimportしてやってもいけるのでは?
というわけで検証してみました。
検証環境
- Centos : 7
- Python : 3.7.1
- Django : 2.1.7
上記の環境で、こちらのチュートリアルに沿ってPollsのviewを作って、そのviewをPythonスクリプトからWSGIを通して呼び出してみました。
Pythonスクリプトの内容
以下が、applicationを呼び出すkick_wsgi.py
スクリプトです。
# wsgi.pyファイルのapplicationエントリポイントのimport
from mysite.wsgi import application
# applicationに渡すメソッド
# 検証だけなので適当、表示のみ
def start_response(status, response_headers):
print('status => %s' % status)
print('response_headers => %s' % response_headers)
# applicationでGETメソッドを動作させる為に必要な最低限のパラメータ
environ = {}
environ['PATH_INFO'] = '/polls/'
environ['REQUEST_URI'] = '/polls/'
environ['REQUEST_METHOD'] = 'GET'
environ['SERVER_NAME'] = 'localhost.localdomain'
environ['SERVER_PORT'] = '80'
environ['wsgi.input'] = '' # これは謎、無いと怒られる
# application呼び出し
response = application(environ, start_response)
# HTMLのコンテンツ表示
print('content => %s' % response.content)
applicationの第2引数:start_responseはdjangoの結果を受け取るだけなんでここでは適当です。重要なのは第1引数:environで、上記のスクリプトを見るとenvironで渡すパラメータには見覚えのあるパラメータ名が並んでいると思います。とりあえずdjangoを騙くらかして動かせればいいんで、最低限必要そうなのをセットしてます。
スクリプトの実行結果
[guest@localhost hoge]$ PYTHONPATH=. python kick_wsgi.py
status => 200 OK
response_headers => [('Content-Type', 'text/html; charset=utf-8'), ('X-Frame-Options', 'SAMEORIGIN'), ('Content-Length', '40')]
content => b"Hello, world. You're at the polls index."
想定通りの結果が返ってきました!
まとめ
djangoをWSGIを使ってキックするのは思いのほかシンプルで簡単でした。シンプルだからこそ、WSGIに対応しているWebサーバやWebアプリであれば部品のように交換して動作させられるんでしょう。
あと私のようなターミナル大好き人間にとってはフレームワークやらなんやらをターミナルから直接叩ける方法があると嬉しかったりするのでこの記事は備忘録用でもあります。(ターミナルから直接叩けて何が嬉しいのか・・それはターミナル好きにしかわからない・・)