From 4d4ae9602207c4111e60373d6cb00475d8bf68c1 Mon Sep 17 00:00:00 2001 From: yuetsh <517252939@qq.com> Date: Tue, 15 Jul 2025 19:09:45 +0800 Subject: [PATCH] test for ws --- api/asgi.py | 12 ++++++++++-- api/settings.py | 12 ++++++++++++ api/urls.py | 5 +++++ api/ws.py | 11 +++++++++++ pyproject.toml | 2 ++ requirements.txt | 3 +++ uv.lock | 50 ++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 93 insertions(+), 2 deletions(-) create mode 100644 api/ws.py diff --git a/api/asgi.py b/api/asgi.py index 1062d02..5875ab8 100644 --- a/api/asgi.py +++ b/api/asgi.py @@ -9,8 +9,16 @@ https://docs.djangoproject.com/en/5.1/howto/deployment/asgi/ import os +from channels.routing import ProtocolTypeRouter, URLRouter +from channels.auth import AuthMiddlewareStack from django.core.asgi import get_asgi_application +from .urls import ws_urlpatterns -os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'api.settings') +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "api.settings") -application = get_asgi_application() +application = ProtocolTypeRouter( + { + "http": get_asgi_application(), + "websocket": AuthMiddlewareStack(URLRouter(ws_urlpatterns)), + } +) diff --git a/api/settings.py b/api/settings.py index 4b7ec0f..cb109f1 100644 --- a/api/settings.py +++ b/api/settings.py @@ -47,6 +47,7 @@ INSTALLED_APPS = [ "django.contrib.sessions", "django.contrib.messages", "django.contrib.staticfiles", + "channels", "ninja", "corsheaders", "django_extensions", @@ -86,6 +87,8 @@ TEMPLATES = [ WSGI_APPLICATION = "api.wsgi.application" +ASGI_APPLICATION = "api.asgi.application" + # Database # https://docs.djangoproject.com/en/5.1/ref/settings/#databases @@ -129,6 +132,15 @@ else: # 配置缓存 CACHES = PROD_CACHES + CHANNEL_LAYERS = { + "default": { + "BACKEND": "channels_redis.core.RedisChannelLayer", + "CONFIG": { + "hosts": [(os.getenv("REDIS_HOST"), 6379)], + }, + }, + } + # Password validation # https://docs.djangoproject.com/en/5.1/ref/settings/#auth-password-validators diff --git a/api/urls.py b/api/urls.py index cec5f6f..80dbc34 100644 --- a/api/urls.py +++ b/api/urls.py @@ -20,6 +20,7 @@ from django.urls import path from django.conf import settings from django.conf.urls.static import static from ninja import NinjaAPI +from .ws import Consumer api = NinjaAPI() @@ -35,3 +36,7 @@ apis = [ ] urlpatterns = apis + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) + +ws_urlpatterns = [ + path("ws/", Consumer.as_asgi()), +] diff --git a/api/ws.py b/api/ws.py new file mode 100644 index 0000000..0b6eae2 --- /dev/null +++ b/api/ws.py @@ -0,0 +1,11 @@ +from channels.generic.websocket import AsyncWebsocketConsumer + +class Consumer(AsyncWebsocketConsumer): + async def connect(self): + await self.accept() + + async def disconnect(self): + pass + + async def receive(self, text_data): + await self.send(text_data=text_data) diff --git a/pyproject.toml b/pyproject.toml index af2ed64..0c5316d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,4 +16,6 @@ dependencies = [ "uvicorn>=0.34.0", "django-redis>=5.4.0", "redis>=5.0.1", + "channels>=4.2.2", + "channels-redis>=4.2.1", ] diff --git a/requirements.txt b/requirements.txt index 877207b..9e45547 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,7 @@ annotated-types==0.7.0 asgiref==3.9.1 +channels==4.2.2 +channels-redis==4.2.1 click==8.2.1 django==5.2.4 django-cors-headers==4.7.0 @@ -11,6 +13,7 @@ email-validator==2.2.0 gunicorn==23.0.0 h11==0.16.0 idna==3.10 +msgpack==1.1.1 packaging==25.0 psycopg==3.2.9 psycopg-binary==3.2.9 diff --git a/uv.lock b/uv.lock index 01c1e99..06d5cf3 100644 --- a/uv.lock +++ b/uv.lock @@ -20,6 +20,34 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/7c/3c/0464dcada90d5da0e71018c04a140ad6349558afb30b3051b4264cc5b965/asgiref-3.9.1-py3-none-any.whl", hash = "sha256:f3bba7092a48005b5f5bacd747d36ee4a5a61f4a269a6df590b43144355ebd2c", size = 23790, upload-time = "2025-07-08T09:07:41.548Z" }, ] +[[package]] +name = "channels" +version = "4.2.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "asgiref" }, + { name = "django" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/16/d6/049f93c3c96a88265a52f85da91d2635279261bbd4a924b45caa43b8822e/channels-4.2.2.tar.gz", hash = "sha256:8d7208e48ab8fdb972aaeae8311ce920637d97656ffc7ae5eca4f93f84bcd9a0", size = 26647, upload-time = "2025-03-30T14:59:20.35Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cc/bf/4799809715225d19928147d59fda0d3a4129da055b59a9b3e35aa6223f52/channels-4.2.2-py3-none-any.whl", hash = "sha256:ff36a6e1576cacf40bcdc615fa7aece7a709fc4fdd2dc87f2971f4061ffdaa81", size = 31048, upload-time = "2025-03-30T14:59:18.969Z" }, +] + +[[package]] +name = "channels-redis" +version = "4.2.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "asgiref" }, + { name = "channels" }, + { name = "msgpack" }, + { name = "redis" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c7/6d/c379c9feea4522cbdb4eba9b3d23a6270ba8cbd94e847b21834d898109d6/channels_redis-4.2.1.tar.gz", hash = "sha256:8375e81493e684792efe6e6eca60ef3d7782ef76c6664057d2e5c31e80d636dd", size = 31152, upload-time = "2024-11-15T12:58:49.836Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a6/aa/981d08ae9627c3b9d8dd150f0fe644122a351abc1f47bcf53d2bfff80d91/channels_redis-4.2.1-py3-none-any.whl", hash = "sha256:2ca33105b3a04b5a327a9c47dd762b546f30b76a0cd3f3f593a23d91d346b6f4", size = 20487, upload-time = "2024-11-15T12:58:47.847Z" }, +] + [[package]] name = "click" version = "8.2.1" @@ -158,6 +186,24 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442, upload-time = "2024-09-15T18:07:37.964Z" }, ] +[[package]] +name = "msgpack" +version = "1.1.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/45/b1/ea4f68038a18c77c9467400d166d74c4ffa536f34761f7983a104357e614/msgpack-1.1.1.tar.gz", hash = "sha256:77b79ce34a2bdab2594f490c8e80dd62a02d650b91a75159a63ec413b8d104cd", size = 173555, upload-time = "2025-06-13T06:52:51.324Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a1/38/561f01cf3577430b59b340b51329803d3a5bf6a45864a55f4ef308ac11e3/msgpack-1.1.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:3765afa6bd4832fc11c3749be4ba4b69a0e8d7b728f78e68120a157a4c5d41f0", size = 81677, upload-time = "2025-06-13T06:52:16.64Z" }, + { url = "https://files.pythonhosted.org/packages/09/48/54a89579ea36b6ae0ee001cba8c61f776451fad3c9306cd80f5b5c55be87/msgpack-1.1.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8ddb2bcfd1a8b9e431c8d6f4f7db0773084e107730ecf3472f1dfe9ad583f3d9", size = 78603, upload-time = "2025-06-13T06:52:17.843Z" }, + { url = "https://files.pythonhosted.org/packages/a0/60/daba2699b308e95ae792cdc2ef092a38eb5ee422f9d2fbd4101526d8a210/msgpack-1.1.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:196a736f0526a03653d829d7d4c5500a97eea3648aebfd4b6743875f28aa2af8", size = 420504, upload-time = "2025-06-13T06:52:18.982Z" }, + { url = "https://files.pythonhosted.org/packages/20/22/2ebae7ae43cd8f2debc35c631172ddf14e2a87ffcc04cf43ff9df9fff0d3/msgpack-1.1.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d592d06e3cc2f537ceeeb23d38799c6ad83255289bb84c2e5792e5a8dea268a", size = 423749, upload-time = "2025-06-13T06:52:20.211Z" }, + { url = "https://files.pythonhosted.org/packages/40/1b/54c08dd5452427e1179a40b4b607e37e2664bca1c790c60c442c8e972e47/msgpack-1.1.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4df2311b0ce24f06ba253fda361f938dfecd7b961576f9be3f3fbd60e87130ac", size = 404458, upload-time = "2025-06-13T06:52:21.429Z" }, + { url = "https://files.pythonhosted.org/packages/2e/60/6bb17e9ffb080616a51f09928fdd5cac1353c9becc6c4a8abd4e57269a16/msgpack-1.1.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e4141c5a32b5e37905b5940aacbc59739f036930367d7acce7a64e4dec1f5e0b", size = 405976, upload-time = "2025-06-13T06:52:22.995Z" }, + { url = "https://files.pythonhosted.org/packages/ee/97/88983e266572e8707c1f4b99c8fd04f9eb97b43f2db40e3172d87d8642db/msgpack-1.1.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b1ce7f41670c5a69e1389420436f41385b1aa2504c3b0c30620764b15dded2e7", size = 408607, upload-time = "2025-06-13T06:52:24.152Z" }, + { url = "https://files.pythonhosted.org/packages/bc/66/36c78af2efaffcc15a5a61ae0df53a1d025f2680122e2a9eb8442fed3ae4/msgpack-1.1.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4147151acabb9caed4e474c3344181e91ff7a388b888f1e19ea04f7e73dc7ad5", size = 424172, upload-time = "2025-06-13T06:52:25.704Z" }, + { url = "https://files.pythonhosted.org/packages/8c/87/a75eb622b555708fe0427fab96056d39d4c9892b0c784b3a721088c7ee37/msgpack-1.1.1-cp313-cp313-win32.whl", hash = "sha256:500e85823a27d6d9bba1d057c871b4210c1dd6fb01fbb764e37e4e8847376323", size = 65347, upload-time = "2025-06-13T06:52:26.846Z" }, + { url = "https://files.pythonhosted.org/packages/ca/91/7dc28d5e2a11a5ad804cf2b7f7a5fcb1eb5a4966d66a5d2b41aee6376543/msgpack-1.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:6d489fba546295983abd142812bda76b57e33d0b9f5d5b71c09a583285506f69", size = 72341, upload-time = "2025-06-13T06:52:27.835Z" }, +] + [[package]] name = "packaging" version = "25.0" @@ -325,6 +371,8 @@ name = "webapi" version = "0.1.0" source = { virtual = "." } dependencies = [ + { name = "channels" }, + { name = "channels-redis" }, { name = "django" }, { name = "django-cors-headers" }, { name = "django-extensions" }, @@ -340,6 +388,8 @@ dependencies = [ [package.metadata] requires-dist = [ + { name = "channels", specifier = ">=4.2.2" }, + { name = "channels-redis", specifier = ">=4.2.1" }, { name = "django", specifier = ">=5.1.6" }, { name = "django-cors-headers", specifier = ">=4.7.0" }, { name = "django-extensions", specifier = ">=3.2.3" },