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に続きます.