使用
python manage.py runserver
运行我的项目可以使用通道 asgi 开发服务器完美启动它,但是当使用 Daphne (daphne project.routing:application
) 运行项目时,我收到错误 AppRegistryNotReady: Apps aren't loaded yet
。
settings.py
INSTALLED_APPS = [
'channels',
'whitenoise.runserver_nostatic',
'django.contrib.staticfiles',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.sites',
# ...
# ... installed apps and custom apps
]
WSGI_APPLICATION = 'project.wsgi.application'
ASGI_APPLICATION = 'project.routing.application'
CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels_redis.core.RedisChannelLayer',
'CONFIG': {
"hosts": [REDIS_URL],
}
},
}
routing.py
import os
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
from django.core.asgi import get_asgi_application
from django.conf.urls import url
from my_app.consumers import MyCustomConsumer
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project.settings")
application = ProtocolTypeRouter({
"http": get_asgi_application(),
'websocket': AuthMiddlewareStack(
URLRouter([
url(r'^ws/custom/$', MyCustomConsumer),
])
),
})
我尝试按照其他问题中的描述添加
django.setup()
,以及使用uvicorn
而不是daphne
运行,但仍然遇到相同的错误。我还尝试指向 settings.CHANNEL_LAYERS['ROUTING']
中的 websocket 路由并将应用程序初始化移至 asgi.py
文件,但也没有运气。我不知道我在做什么与渠道文档不同,任何帮助表示赞赏。
尽早获取 Django ASGI 应用程序以确保填充 AppRegistry 在导入消费者和可能导入 ORM 的 AuthMiddlewareStack 之前 型号。
import os
from django.conf.urls import url
from django.core.asgi import get_asgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project.settings")
django_asgi_app = get_asgi_application()
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
from my_app.consumers import MyConsumer
application = ProtocolTypeRouter({
# Django's ASGI application to handle traditional HTTP requests
"http": django_asgi_app,
# WebSocket chat handler
"websocket": AuthMiddlewareStack(
URLRouter([
path('ws/custom/', MyConsumer),
])
),
})
asgi.py
import os
import django
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'chat.settings')
django.setup()
from django.core.asgi import get_asgi_application
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.auth import AuthMiddlewareStack
from chat import routing
application = ProtocolTypeRouter({
'http': get_asgi_application(),
"websocket": AuthMiddlewareStack(
URLRouter(
routing.websocket_urlpatterns
)
)
})
上面提到的对我来说没有任何作用。但我尝试使用以下配置在本地计算机上工作:
import os
from django.core.asgi import get_asgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'app.settings')
django_asgi_app = get_asgi_application()
from channels.routing import ProtocolTypeRouter, URLRouter
from app.tokenAuthMiddleware import TokenAuthMiddleware
from app.routing import channel_routing
application = ProtocolTypeRouter({
"http": django_asgi_app,
"websocket": TokenAuthMiddleware(
URLRouter(channel_routing)
)
})
然后运行以下命令:
gunicorn app.asgi:application -k uvicorn.workers.UvicornH11Worker
使用
UvicornH11Worker
而不是 UvicornWorker
对我有用。
您可以查看以下链接作为参考: uvicorn 与 Gunicorn 一起奔跑
问题源自将 daphne 服务器指向
routing.py
中的应用程序,而它需要指向 asgi.py
文件。但是,在 settings.py
内,ASGI_APPLICATION
需要指向 routing.py
文件中的应用程序。
asgi.py
import os
import django
from channels.routing import get_default_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project.settings")
django.setup()
application = get_default_application()
设置.py
ASGI_APPLICATION = 'project.routing.application'
路由.py
import os
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
from django.urls import path
from my_app.consumers import MyConsumer
application = ProtocolTypeRouter({
'websocket': AuthMiddlewareStack(
URLRouter([
path('ws/custom/', MyConsumer),
])
),
})
然后使用
daphne project.asgi:application
运行 daphne 服务器
对于使用 Django > 3.0 的任何人,请参阅下面的链接:
https://github.com/django/channels/issues/1564#issuecomment-722354397
您要做的就是在导入其他内容之前调用 get_asgi_application()
我的 asgi.py 文件示例:
import os
from django.core.asgi import get_asgi_application
from channels.routing import ProtocolTypeRouter
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'project.settings')
django_asgi_app = get_asgi_application()
from django.conf import settings
from .routing import asgi_routes
asgi_routes["http"] = django_asgi_app
application = ProtocolTypeRouter(asgi_routes)