37
23

More than 3 years have passed since last update.

Django3.0のリリースを祝してWSGIの精神的後継であるASGIを試してみたがwebsocketは使えなかった

Last updated at Posted at 2019-12-06

祝!Django 3.0 リリース!

2019/12/02 Django 3.0がリリースされました。
Django 1.0がリリースされたのが2008年、2.0のリリースが2017年12月です。そして今年の12/2に3.0がリリースされました。
1から2へのバージョンアップが約10年かけたのに対して、2から3まで2年足らずという驚きのスピード感です。それに比べてこの2年間、私はいったい何をしていたのでしょうか?それではDjango 3.0で個人的に気になった新機能を見てみたいと思います!

ASGI supportとは

私はこれが気になりました。とは言ってもASGIというものを触ったことがなくて、これを公式サポートしました!と言われても、ほーん、という感じでした。でも俺にはWSGIさんがついているから・・・と。
しかし、調べてみるとどうやらASGIさんは無視できない存在っぽいようにだんだんと思えてきました。

リリースノートによると、現在、非同期機能はWSGIにはなくてASGIで実行された時のみサポートされているとあるし(でも将来的にはサポートするみたい?)。
ASGIの公式が言うには、「ASGIはWSGIのspiritual successor(精神的続編)」らしいですし。
こうしてみると私の強い味方に思えていたWSGIが、ASGIの下位互換なのではないかと思えてきました。

関係ないですけど、精神的続編って言葉、なんかカッコイイですね。ゼノギアスに対するゼノサーガ、ゴールデンアイ007に対するパーフェクトダーク等がそれに該当してくるみたいです。しかし、WSGIやASGIは別にゲームやフィクション作品って訳ではなく、続編という訳は果たして適しているだろうか?と思ったので精神的後継と読んでみようと思います。タイトルにもそう書きました。

ASGIでDjangoを動かしてみる

そうと決まれば話は早いってことで、試しにDjangoをASGIで動かしてみました。Dockerで環境を作って。

sudo docker run --rm -it -p 8000:8000 python:3.8 bash

python3.8を使います。ところでDjango 3.0はpython 3.6、3.7、および3.8をサポートしています。

pip install django daphne

djangoと一緒にdaphneもインストールします。daphneASGI用のサーバみたいですね。WSGIにおけるuWSGIASGIにおけるdaphneなのでしょう。きっと。
ちなみにdaphneはダフネと呼ぶらしいです。djangoはジャンゴなのに、daphneのdはちゃんと発音してもらえていいですね。

django-admin startproject app
cd app
daphne -b 0.0.0.0 -p 8000 app.asgi:application

インストールしたらプロジェクトを作って早速動かしてみます。

やった!動いた!完!

django3.png

動いたけどこれだと何が嬉しいのかが分からない。まあ、当然ですよね。非同期機能が売りなのに同期通信しかしてないですし。

Djangoで非同期通信が試せるチャットアプリを構築するようなチュートリアルとかはないだろうか・・・

ありました。
https://channels.readthedocs.io/en/latest/tutorial/index.html
Django channelsが使うとDjangでweb socketが使えるみたいでして、ご丁寧にチャットアプリのチュートリアルがあります。これを写経して作ったチャットアプリをdaphneで動かしてみよう、という魂胆です。
しかし、Django channelsと今回のASGIサポートの関係性がイマイチよく分かってないです。まあ、でも使っているうちに分かってくるかもしれないので深入りしないでおきます。

ここにチュートリアルに沿って作った完成品をここに置いておきます。
ためしに動かしてみます。command: python manage.py runserver 0.0.0.0:8000の状態です。

sudo docker-compose up -d

2窓で動作確認しましたが、ちゃんとチャットが使えますね。

mov2.gif

では、これをdaphneで動かしてみます。commandを次のように書き換えます。

 services:
     app:
         build: .
-        command: python manage.py runserver 0.0.0.0:8000
+        command: daphne -b 0.0.0.0 -p 8000 mysite.asgi:application
         volumes:
             - .:/srv
         ports:

私の予想だとこれでも動くはずですが・・・。

sudo docker-compose down
sudo docker-compose up -d

ws.png
んー、動きませんね。

なにやらエラーメッセージを読むとwebsocketは使えないって書いてありますね。

172.17.0.1:52480 - - [06/Dec/2019:07:36:28] "GET /chat/a/" 200 1413
172.17.0.1:52488 - - [06/Dec/2019:07:36:28] "WSCONNECTING /ws/chat/a/" - -
2019-12-06 07:36:29,471 ERROR    Exception inside application: Django can only handle ASGI/HTTP connections, not websocket.
  File "/usr/local/lib/python3.8/site-packages/daphne/cli.py", line 30, in asgi
    await self.app(scope, receive, send)
  File "/usr/local/lib/python3.8/site-packages/django/core/handlers/asgi.py", line 144, in __call__
    raise ValueError(
  Django can only handle ASGI/HTTP connections, not websocket.
172.17.0.1:52488 - - [06/Dec/2019:07:36:29] "WSDISCONNECT /ws/chat/a/" - -

asgi.pyの144行目付近を見てみましょう。


    async def __call__(self, scope, receive, send):
        """
        Async entrypoint - parses the request and hands off to get_response.
        """
        # Serve only HTTP connections.
        # FIXME: Allow to override this.
        if scope['type'] != 'http':
            raise ValueError(
                'Django can only handle ASGI/HTTP connections, not %s.'
                % scope['type']
            )

HTTP connections以外だった時は例外を投げるようにしているみたいですね。これは一体どういうことでしょう。

  • ASGI supportがまだweb socketに対応していない
  • django channelsのチュートリアルのチャットアプリをDjango3.0を使ってdaphne app.asgi:applicationで動かそうとする考えがそもそも間違ってる

どっちかだと思ますが、良くはわかってません。謎は深まるばかりです。しかし、ASGIでDjangoを非同期対応できるというのは公式でも謳っていることではあるので、今後とも注視していこうと思います。

おわり

さよならWSGIさん。俺にはASGIさんがいるから・・・

37
23
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
37
23