DjangoでWebsocketを使う場合は「Channels」を使うのが一般的らしい。
今回は「Channels」を使って実装したときに以下のようなエラーに遭遇したので、同じ悩みを持つ方へ解決方法を共有しておく。
Exception inside application: object.__init__() takes exactly one argument (the instance to initialize)
Exception inside application...
このエラーが起きる原因はおそらくWebsocketConsumer
クラスを継承してなんやかんやしてる場合です。
「Channels」を使ってwebsocketを実装する方法はいくつかありますが、WebsocketConsumerクラスを継承すると割とサクッと実装できる気がします。ですが、ここで今回のようなエラーに遭遇する方もいるのではないでしょうか。
consumers.py
class WSConsumer(WebsocketConsumer):
def connect(self):
self.accept()
def disconnect(self, close_code):
pass
def receive(self, text_data):
text_data_json = json.loads(text_data)
message = text_data_json['message']
self.send(text_data=json.dumps({
'message': message
}))
routing.py
from django.urls import path
from . import consumers
websocket_urlpatterns = [
path('ws/<slug:room_name>/', consumers.WSConsumer), #後ほど説明しますが、この部分が問題です。
]
WebSocketのテストとしてオウム返しに入力値を表示するプログラムを実装したときの一部分になります。WebsocketConsumer
を継承しています。
原因はpython3.6以上を使っているから
今回のException inside application: object.init() takes exactly one argument (the instance to initialize)
エラーの原因はpython3.6以上を使っているからでした。
python3.6からWebsocketConsumer
クラスの呼び出し方が変更されたようです。
以下のようにrouting.py
のクラス呼び出し部分を変更します。as_asgi()
を付けます。
websocket_urlpatterns = [
path('ws/<slug:room_name>/', consumers.WSConsumer.as_asgi()),
]
これで、python3.6以上で「Channels」を使ったWebSocketハンドシェイクエラーが解決しました。
pythonの互換性を考慮する
python3.6未満の場合はこれだと動きません。なので、どのバージョンでも動くようにするためには以下のように実装します。お使いの環境等を考慮して必要であれば実装してみてください。
routing.py
from django.urls import path
from . import consumers
if float(platform.python_version()[0:3]) > 3.6:
cons = consumers.WSConsumer.as_asgi()
else:
cons = consumers.WSConsumer
websocket_urlpatterns = [
path('ws/<slug:room_name>/', cons),
]
これで解決。ばいちゃ
コメント