Django 2.0 + Channels 2.1 でチュートリアルやっていく(1)
はじめに
channelsの公式チュートリアルを順番にやっていこうというだけのものです.Djangoの基礎知識に関しては一切触れません.ご了承ください.
そろそろWebSocketもやらないとね?って天の声に言われたので,今回はTutorial Part 1: Basic Setupからやっていきます.Django 2.0を使用しているので,チュートリアルとところどころコードが違います.
環境構築
あらかじめ断っておくとWindowsではやりません.
仮想環境としてvenvを使用していきます.
$ python3 -V 3.6.0 $ python3 -m venv env $ source env/bin/activate
必要なライブラリをインストールします
$ pip install --upgrade pip $ pip install django channels $ pip freeze asgiref==2.3.0 async-timeout==2.0.1 attrs==18.1.0 autobahn==18.4.1 Automat==0.6.0 channels==2.1.1 constantly==15.1.0 daphne==2.1.1 Django==2.0.5 hyperlink==18.0.0 idna==2.6 incremental==17.5.0 pytz==2018.4 six==1.11.0 Twisted==18.4.0 txaio==2.10.0 zope.interface==4.5.0
今回作るもの
In this tutorial we will build a simple chat server. It will have two pages:
・ An index view that lets you type the name of a chat room to join.
・ A room view that lets you see messages posted in a particular chat room.The room view will use a WebSocket to communicate with the Django server and listen for any messages that are posted.
とあるように,チャットアプリケーションを作成します.
仕様
- 2つのページを作る
- 参加するチャットルームの名前を入力する初期ページ
- 特定のルームに投稿されたメッセージを見れるルームページ
- ルームのページではWebSocketを使用してDjangoサーバとの通信を行う
Tutorial Part1: Basic Setup
アプリケーション初期設定
プロジェクト名はchannels_tutorial1,アプリケーション名はchatとします.
$ django-admin startproject channels_tutorial1 $ cd channels_tutorial1 $ python manage.py startapp chat $ tree -L 2 . ├── channels_tutorial1 │ ├── __init__.py │ ├── __pycache__ │ ├── settings.py │ ├── urls.py │ └── wsgi.py ├── chat │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── migrations │ ├── models.py │ ├── tests.py │ └── views.py └── manage.py 4 directories, 11 files
settings.pyを日本語環境向けに編集します.106~108行目あたりです.
LANGUAGE_CODE = 'ja-jp' TIME_ZONE = 'Asia/Tokyo'
シークレットキーがそのまま埋め込まれているのが精神的に良くないのでdotenvで分離します.
$ pip install python-dotenv
manage.pyと同じディレクトリに下記のような.envファイルを用意します.値は適当に入れてください.
SECRET_KEY=f%1(dv)6-)sadf3-c+vr*8b1j&2=^38o^&i!ekni6%=y^sxogsdif DEBUG=True
dotenv.load_dotenvで.envファイルをロードします.
import os import dotenv BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # .envを読み込み dotenv.load_dotenv(os.path.join(BASE_DIR, '.env')) SECRET_KEY = os.getenv('SECRET_KEY') DEBUG = os.getenv('DEBUG', 'False').lower() == 'true'
INSTALLED_APPSにchatアプリを追加します
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'chat'
]
初期ページ追加
chatディレクトリの中にテンプレートを入れるためのtemplatesディレクトリを作成し,更に中にchatディレクトリを作成,index.htmlを配置します.
$ pwd /path/to/channels_tutorial1 $ cd chat $ mkdir templates $ cd templates $ mkdir chat $ touch chat/index.html
index.htmlを下記のように編集します.
<!DOCTYPE html> <html> <head> <meta charset="utf-8"/> <title>Chat Rooms</title> </head> <body> What chat room would you like to enter?<br/> <input id="room-name-input" type="text" size="100"/><br/> <input id="room-name-submit" type="button" value="Enter"/> </body> <script> document.querySelector('#room-name-input').focus(); document.querySelector('#room-name-input').onkeyup = function(e) { if (e.keyCode === 13) { // enter, return document.querySelector('#room-name-submit').click(); } }; document.querySelector('#room-name-submit').onclick = function(e) { var roomName = document.querySelector('#room-name-input').value; window.location.pathname = '/chat/' + roomName + '/'; }; </script> </html>
chat/views.pyに下記の様にindex.htmlをrenderして返す関数を定義します.
from django.shortcuts import render def index(request): return render(request, 'chat/index.html', {})
chat/urls.pyを作成し,下記の様にindexへのurlpatternを定義します.
from django.urls import path from .views import index urlpatterns = [ # 元のコードは→url(r'^$', views.index, name='index'), path('', index, name='index'), ]
settings.pyと同階層にあるurls.pyがルートになっているので,ここからchat/urls.pyを取り込みます.
from django.contrib import admin from django.urls import path, include from chat import urls as chat_urls urlpatterns = [ # 元のコードは→url(r'^chat/', include('chat.urls')), path('chat/', include(chat_urls)), # 元のコードは→url(r'^admin/', admin.site.urls), path('admin/', admin.site.urls), ]
ここまで出来たら一度runserverで動かして,http://127.0.0.1:8000/chat/にアクセスしてみます.
$ python manage.py runserver System check identified no issues (0 silenced). May 05, 2018 - 01:07:36 Django version 2.0.5, using settings 'channels_tutorial1.settings' Starting development server at http://127.0.0.1:8000/ Quit the server with CONTROL-C.
下記の様なページが表示されると思います.

ASGI/Channelsサーバの起動
ここまでは標準のDjangoの機能を使用してきましたが,ここからはchannelsモジュールを使用して行きます.
まず,channelsが用いるルーティングファイルを記述します.これはurls.pyのようなものに相当するようです.channels_tutorial1/routing.pyを作成し下記の様に編集します.
from channels.routing import ProtocolTypeRouter
application = ProtocolTypeRouter({
# (http->django views is added by default)
})
INSTALLED_APPSにchannelsを追加し,ASGI_APPLICATIONを定義します.
INSTALLED_APPS = [
# 省略
'chat',
'channels',
]
ASGI_APPLICATION = 'channels_tutorial1.routing.application'
runserverしてみると,先ほどとは違う,ASGI/Channelsサーバが起動します((チュートリアルではこれがいくつかのrunserverをラップしてしまうようなコマンドに対して競合する可能性を示唆しています.例えば静的ファイルを配信する設定を簡便にするwhitenoiseなどがその筆頭のようで,その場合はchannelsをINSTALLED_APPSの先頭に持ってくる,それらのアプリケーションを削除するなどが対策として上げられています.)).
$ python manage.py runserver Performing system checks... System check identified no issues (0 silenced). May 05, 2018 - 01:16:55 Django version 2.0.5, using settings 'channels_tutorial1.settings' Starting ASGI/Channels version 2.1.1 development server at http://127.0.0.1:8000/ Quit the server with CONTROL-C. 2018-05-05 01:16:55,548 - INFO - server - HTTP/2 support not enabled (install the http2 and tls Twisted extras) 2018-05-05 01:16:55,548 - INFO - server - Configuring endpoint tcp:port=8000:interface=127.0.0.1 2018-05-05 01:16:55,555 - INFO - server - Listening on TCP address 127.0.0.1:8000
再びhttp://127.0.0.1:8000にアクセスし,表示されれば完了です.次回Part 2に続きます.