channels icon indicating copy to clipboard operation
channels copied to clipboard

SynchronousOnlyOperation django app ready and database call failed

Open kojibhy opened this issue 2 years ago • 2 comments

from django.apps import AppConfig

def refresh_cache_from_db():
    from test_app.models import TestModel
     for c in TestModel.objects.all():
         redis_cache_store.set(c.name, c, timeout=None)

 
class TestConfig(AppConfig):
    name = 'applications.test'

    def ready(self):
        refresh_cache_from_db()

wsgi.py works perfect but asgi.py channels will failed with error django.core.exceptions.SynchronousOnlyOperation: You cannot call this from an async context - use a thread or sync_to_async.

in my app i use wsgi.py for handle requests and asgi.py only for websockets how to solve this problem?

kojibhy avatar Aug 13 '22 10:08 kojibhy

Can you post the whole traceback please

carltongibson avatar Aug 13 '22 13:08 carltongibson

|   File "/app/./core/asgi.py", line 9, in <module>
|     django_asgi_app = get_asgi_application()
|   File "/usr/local/lib/python3.10/site-packages/django/core/asgi.py", line 12, in get_asgi_application
|     django.setup(set_prefix=False)
|   File "/usr/local/lib/python3.10/site-packages/django/__init__.py", line 24, in setup
|     apps.populate(settings.INSTALLED_APPS)
|   File "/usr/local/lib/python3.10/site-packages/django/apps/registry.py", line 124, in populate
|     app_config.ready()
|   File "/app/project/test/apps.py", line 12, in ready
|     redis_from_db_refresh()
|   File "/app/project/test/services/redis_build_cache.py", line 14, in redis_from_db_refresh
|     for i in TestModel.objects.all():
|   File "/usr/local/lib/python3.10/site-packages/django/db/models/query.py", line 320, in __iter__
|     self._fetch_all()
|   File "/usr/local/lib/python3.10/site-packages/django/db/models/query.py", line 1507, in _fetch_all
|     self._result_cache = list(self._iterable_class(self))
|   File "/usr/local/lib/python3.10/site-packages/django/db/models/query.py", line 57, in __iter__
|     results = compiler.execute_sql(
|   File "/usr/local/lib/python3.10/site-packages/django/db/models/sql/compiler.py", line 1359, in execute_sql
|     cursor = self.connection.cursor()
|   File "/usr/local/lib/python3.10/site-packages/django/utils/asyncio.py", line 24, in inner
|     raise SynchronousOnlyOperation(message)
| django.core.exceptions.SynchronousOnlyOperation: You cannot call this from an async context - use a thread or sync_to_async.

kojibhy avatar Aug 13 '22 15:08 kojibhy

Yes... OK...

Making DB queries in ready() is not supported. See the warning in the AppConfig.ready docs

I'd move this logic to your project's wsgi.py and asgi.py files respectively, using sync_to_async() in the latter case.

carltongibson avatar Aug 19 '22 07:08 carltongibson