チャットアプリへの道②

しばらくあれこれとやっていて間が空いてしまいましたが、ようやくローカルで動かすことに成功したので書き留めておきましょう。

注意:こちらのページは、作成者seijiが勉強も兼ねてとの意味合いで、インターネットの情報をもとにトライした記録です。正常な動作を保証する事は一切致しかねます。

環境

使用端末:MacbookPro (OS:Catalina10.15.7)
ITerm2
shell : zsh
Python: ver 3.8.8
Django: ver 4.0
Channels: ver 3.0.4
channels-redis: ver 3.3.1


・Mac上で仮想環境を構築し、Django,Channels,WebSocketを利用。
・SERVER : WEBサーバ ➡️ Djangoを利用し、仮想ローカルサーバを設定。
      キャッシュサーバ ➡️ Redis をインストール。

・ DATABASE : SQLite3

仮想環境の設定

チャットアプリ用のディレクトリ「Mychat」を作成し、Mychatへ移動

%cd Mychat

Mychat上でPythonの仮想環境を構築

Mychat% python -m venv .venv

構築した仮想環境上に移動

Mychat% source .venv/bin/activate

注)MacOSの場合。Windowsの場合は、.venv/Scripts/activate.bat となる模様。
➡️ターミナルでのプロンプト先頭に、(.venv)と表示される。
 終了する場合は、「deactivate」コマンドを実行。

Pythonパッケージの一括インストール

目的:使用するPythonパッケージ(Django,Channels,channels-redis)を一括でインストールする。

①「Mychat」ディレクトリの下に、「requirement.txt」ファイルを作成

django
channels
channels-redis

②ターミナル上で、下記コマンドを実行

% python -m pip install -r requirement.txt

③下記コマンドを実行し、インストールされたパッケージを確認。

% python -m pip freeze

Djangoプロジェクトの作成

「Mychat」ディレクトリにて下記コマンドを実行し、Djangoプロジェクト「mysite」を作成。

Mychat% django-admin startproject mysite

「mysite」に移動。

Mychat% cd mysite

「mysite」ディレクトリにて下記コマンドを実行し、サーバーを起動。

mysite% python manage.py runserver

注)上記、6行目「ASGI/Channels version 3.0.4」は、Channels有効化後に表示されます。

この状態で、ブラウザにてローカルホスト「127.0.0.1:8000」にアクセスすると、Djangoのインストール完了画面が表示される。

Djangoアプリケーションの作成

「mysite」ディレクトリにてDjangoアプリケーションを作成

% python manage.py startapp chat

作成したアプリケーションを、Djangoプロジェクトに登録。
「mysite/mysite/settings.py」の、「INSTALLED_APPS」の最上部に追記。

INSTALLED_APPS = [
    'chat',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

chat.htmlの作成

htmlファイルを作成。 (Mychat/mysite/chat/templates/chat)

chat% vim chat.html 
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8" />
    <title>Chat</title>
</head>
<body>
    <h1>Chat</h1>
    <form action="" onsubmit="onsubmitButton_Send();return false;">
        Message:<input type="text" id="input_message" autocomplete="off" autofocus/><input type="submit" value="Send" />
    </form>

    <ul id="list_message"></ul>
    
    <script>
	    const g_elementInputMessage = document.getElementById("input_message");
	    const g_elementListMessage = document.getElementById("list_message");

	    //Websocketオブジェクト
	    let ws_scheme = window.location.protocol == "https:" ? "wss" : "ws";
	    const g_socket = new WebSocket(ws_scheme + "://" + window.location.host + "/ws/chat/");

	    //「Send」ボタンを押したときの処理
	    function onsubmitButton_Send()
	    {
	        //送信用テキストHTML要素からメッセージ文字列の取得
            let strMessage = g_elementInputMessage.value;
	        if( !strMessage )
	        {
		        return;
	        }

	        //WebSocketを通したメッセージの受信
	        g_socket.send(JSON.stringify({"message":strMessage}));

	        //送信用テキストHTML要素の中身のクリア
	        g_elementInputMessage.value = "";
	    }

	    //Websocketからのメッセージ受信時の処理
	    g_socket.onmessage = (event) =>
	    {
	        //テキストデータをJSONデータにデコード
		    let data = JSON.parse(event.data);

	        //メッセージの整形
	        let strMessage = data["message"];

	        //拡散されたメッセージをメッセージリストに追加
	        let elementLi = document.createElement("li");
	        elementLi.textContent = strMessage;
	        g_elementListMessage.prepend(elementLi); //リストの一番上に追加
	        //g_elementListMessage.append(elementLi); //リストの一番下に追加
	    };

	    //Websocketクローズ時の処理
	    g_socket.onclose = (event) =>
	    {
	        //ウェブページを閉じた時以外のWebsocketクローズは想定外
	        console.error("Unexpected : Chat socket closed.");
	    };
	</script>
</body>
</html>

chat.html を表示させるための関数を「views.py」に追記。(mysite/chat/views.py)

from django.shortcuts import render

# Create your views here.

def chat( request ):
    return render( request, 'chat/chat.html' )

作成した関数を呼び出すURLパターンを定義。(mysite/chat)
「urls.py」を新規作成。

from django.urls import path

from . import views

urlpatterns = [
    path( '', views.chat, name='chat' ),
]

プロジェクトの「urls.py」に追記。(Mychat/mysite/mysite/urls.py)
・from django.urls import include #include関数をimport
・path(”, include(‘chat.urls’)), #アプリケーションの「urls.py」へパスを通す

・・・省略・・・
from django.contrib import admin
from django.urls import path

from django.urls import include

urlpatterns = [
    path( '', include( 'chat.urls' ) ),
    path('admin/', admin.site.urls),
]

Channelsパッケージをプロジェクトへ登録

ChannelsパッケージをDjangoプロジェクトに登録。
「mysite/mysite/settings.py」の、「INSTALLED_APPS」の最上部に追記。

INSTALLED_APPS = [
    'channels',
    'chat',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

ルーティングに関するコードの追加

下記コードを追記する。(mysite/mysite/asgi.py)
・django_asgi_app = get_asgi_application() #変数名の変更
・from channels.routing import ProtocolTypeRouter #ProtocolTypeRouterをimport
・application = ProtocolTypeRouter(… #applicationの設定コードをProtocolTypeRouterクラスを用いて記述

・・・省略・・・
import os

from django.core.asgi import get_asgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings')

#application = get_asgi_application()
django_asgi_app = get_asgi_application()

from channels.routing import ProtocolTypeRouter

application = ProtocolTypeRouter( {
    'http': django_asgi_app,
} )

「mysite/mysite/settings.py」の最下部に下記を追記。

# Channels
ASGI_APPLICATION = 'mysite.asgi.application'

いったんここまででひと休みしましょう。
続いては、
・Redisの有効化
・メッセージ送受信のためのchat.htmlファイル及びconsumers.pyファイルの作成
となります。

注意:こちらのページは、作成者seijiが勉強も兼ねてとの意味合いで、インターネットの情報をもとにトライした記録です。正常な動作を保証する事は一切致しかねます。


投稿日

カテゴリー:

, , , ,

投稿者:

タグ: