Home > Net >  How to deploy django app with channels and websocket to Heroku?
How to deploy django app with channels and websocket to Heroku?

Time:12-25

I'm creating messanger. I met a need to deploy my app to heroku.

My config/settings.py

from pathlib import Path
from datetime import timedelta
import os

BASE_DIR = Path(__file__).resolve().parent.parent

SECRET_KEY = os.environ.get('SECRET_KEY')

DEBUG = True

ALLOWED_HOSTS = ['*']

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
    'rest_framework_simplejwt',
    'corsheaders',
    'users',
    'tokens',
    'channels',
    'chat',
    'college'
]

AUTH_USER_MODEL = 'users.User'

ASGI_APPLICATION = 'config.asgi.application'

CHANNEL_LAYERS = {
    'default': {
        'BACKEND': 'channels_redis.core.RedisChannelLayer',
        'CONFIG': {
            "hosts": [(os.environ.get('REDIS_URI'), 25690)],
        },
    },
}

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'config.wsgi.application'

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': os.environ.get('ELEPHANT_NAME'),
        'USER': os.environ.get('ELEPHANT_USER'),
        'PASSWORD': os.environ.get('ELEPHANT_PASSWORD'),
        'HOST': os.environ.get('ELEPHANT_HOST'),
        'PORT': 5432
    }
}


STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static')

MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
........................

I user heroku-redis

config.asgi

import os

from channels.routing import ProtocolTypeRouter, URLRouter
from django.core.asgi import get_asgi_application
import chat.routing

from config.middlewares import TokenAuthMiddleware

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings")

application = ProtocolTypeRouter({
  "http": get_asgi_application(),
  "websocket": TokenAuthMiddleware(
        URLRouter(
            chat.routing.websocket_urlpatterns
        )
    ),
})

Procfile

release: python manage.py migrate
web: daphne config.asgi:application --port $PORT --bind 0.0.0.0 -v2
worker: python manage.py runworker channels --settings=core.settings -v2

Honestly I don't know which port i should specify. Don't think it matters so I left 8001

requirements.txt

....................
daphne==3.0.2
Django==3.2.9
gunicorn==20.1.0
hiredis==2.0.0
psycopg2==2.9.2
channels==3.0.4
channels-redis==3.3.1
.....................

error i'm getting

2021-12-24T13:28:26.164337 00:00 heroku[web.1]: State changed from crashed to starting
2021-12-24T13:28:31.530462 00:00 heroku[web.1]: Starting process with command `daphne config.asgi:application --port 59828 --bind 0.0.0.0 -v2`
2021-12-24T13:28:33.068963 00:00 app[web.1]: Traceback (most recent call last):
2021-12-24T13:28:33.068982 00:00 app[web.1]: File "/app/.heroku/python/bin/daphne", line 8, in <module>
2021-12-24T13:28:33.069042 00:00 app[web.1]: sys.exit(CommandLineInterface.entrypoint())
2021-12-24T13:28:33.069044 00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/daphne/cli.py", line 170, in entrypoint
2021-12-24T13:28:33.069151 00:00 app[web.1]: cls().run(sys.argv[1:])
2021-12-24T13:28:33.069160 00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/daphne/cli.py", line 232, in run
2021-12-24T13:28:33.069237 00:00 app[web.1]: application = import_by_path(args.application)
2021-12-24T13:28:33.069247 00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/daphne/utils.py", line 12, in import_by_path
2021-12-24T13:28:33.069292 00:00 app[web.1]: target = importlib.import_module(module_path)
2021-12-24T13:28:33.069294 00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/importlib/__init__.py", line 127, in import_module
2021-12-24T13:28:33.069356 00:00 app[web.1]: return _bootstrap._gcd_import(name[level:], package, level)
2021-12-24T13:28:33.069364 00:00 app[web.1]: File "<frozen importlib._bootstrap>", line 1030, in _gcd_import
2021-12-24T13:28:33.069433 00:00 app[web.1]: File "<frozen importlib._bootstrap>", line 1007, in _find_and_load
2021-12-24T13:28:33.069471 00:00 app[web.1]: File "<frozen importlib._bootstrap>", line 986, in _find_and_load_unlocked
2021-12-24T13:28:33.069568 00:00 app[web.1]: File "<frozen importlib._bootstrap>", line 680, in _load_unlocked
2021-12-24T13:28:33.069569 00:00 app[web.1]: File "<frozen importlib._bootstrap_external>", line 850, in exec_module
2021-12-24T13:28:33.069590 00:00 app[web.1]: File "<frozen importlib._bootstrap>", line 228, in _call_with_frames_removed
2021-12-24T13:28:33.069628 00:00 app[web.1]: File "/app/./config/asgi.py", line 6, in <module>
2021-12-24T13:28:33.069680 00:00 app[web.1]: import chat.routing
2021-12-24T13:28:33.069681 00:00 app[web.1]: File "/app/./chat/routing.py", line 3, in <module>
2021-12-24T13:28:33.069727 00:00 app[web.1]: from . import consumers
2021-12-24T13:28:33.069735 00:00 app[web.1]: File "/app/./chat/consumers.py", line 4, in <module>
2021-12-24T13:28:33.069777 00:00 app[web.1]: from .models import Message, Chat, File
2021-12-24T13:28:33.069785 00:00 app[web.1]: File "/app/./chat/models.py", line 3, in <module>
2021-12-24T13:28:33.069827 00:00 app[web.1]: from users.models import User
2021-12-24T13:28:33.069834 00:00 app[web.1]: File "/app/./users/models.py", line 3, in <module>
2021-12-24T13:28:33.069877 00:00 app[web.1]: from django.contrib.auth.models import AbstractUser, Group
2021-12-24T13:28:33.069885 00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/django/contrib/auth/models.py", line 3, in <module>
2021-12-24T13:28:33.069930 00:00 app[web.1]: from django.contrib.auth.base_user import AbstractBaseUser, BaseUserManager
2021-12-24T13:28:33.069938 00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/django/contrib/auth/base_user.py", line 48, in <module>
2021-12-24T13:28:33.069991 00:00 app[web.1]: class AbstractBaseUser(models.Model):
2021-12-24T13:28:33.069997 00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/django/db/models/base.py", line 108, in __new__
2021-12-24T13:28:33.070056 00:00 app[web.1]: app_config = apps.get_containing_app_config(module)
2021-12-24T13:28:33.070064 00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/django/apps/registry.py", line 253, in get_containing_app_config
2021-12-24T13:28:33.070148 00:00 app[web.1]: self.check_apps_ready()
2021-12-24T13:28:33.070156 00:00 app[web.1]: File "/app/.heroku/python/lib/python3.9/site-packages/django/apps/registry.py", line 136, in check_apps_ready
2021-12-24T13:28:33.070219 00:00 app[web.1]: raise AppRegistryNotReady("Apps aren't loaded yet.")
2021-12-24T13:28:33.070242 00:00 app[web.1]: django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet.
2021-12-24T13:28:33.285009 00:00 heroku[web.1]: Process exited with status 1

How can I solve this? If you need something else me to show you please comment

CodePudding user response:

You need to call get_asgi_application before any models are imported, import chat.routing seems to trigger model imports so call get_asgi_application() before this import

config.asgi

import os

from channels.routing import ProtocolTypeRouter, URLRouter
from django.core.asgi import get_asgi_application

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings")
django_asgi_app = get_asgi_application()

import chat.routing

from config.middlewares import TokenAuthMiddleware

application = ProtocolTypeRouter({
  "http": django_asgi_app,
  "websocket": TokenAuthMiddleware(
        URLRouter(
            chat.routing.websocket_urlpatterns
        )
    ),
})
  • Related