django-constance
django-constance copied to clipboard
Needs `sync_to_async` in async context
Describe the problem
When used in an async view, you need to access the object with a sync_to_async wrapper or this error will get raised:
SynchronousOnlyOperation: You cannot call this from an async context - use a thread or sync_to_async
Steps to reproduce
Create an async view in Django 3.1 and try to access an attribute of the config object.
System configuration
- Django version: 3.1
- Python version: 3.9
- Django-Constance version: 2.8.0
I came here to report something similar. This error also occurs if trying to use constance settings in views.py or urls.py (anything that gets called when Django starts up) when using the latest django-channels and deploying the app with asgi. An example would be using a constance config as a constant in a caching decorator.
Same - django 3.1, python 3.7, latest constance
Any thoughts?
More details:
- py 3.7, django 3.1, daphne 3.0.1, asgref 3.2.10, constance 2.8.0 (latest), no channels
- constance via postgres/redis
- triggering scenario is
urls.pycallsconfig.XYZas part of import
More complete workaround:
from asgiref.sync import sync_to_async
from constance import config
@sync_to_async
def safe_constance_get(fld: str):
return getattr(config, fld)
z = safe_constance_get('Z')
mea culpa, not always the right fix: can get you a <coroutine obj> that'll need to be run
This is a common use case so not sure
https://channels.readthedocs.io/en/stable/topics/databases.html#database-sync-to-async is recommended way to wrap. What changes do you expect in django-constance?
@sergei-iurchenko Hi! Thanks for answering. Considering that the Constance API is as simple as Django's Settings API, It would've been better if the library handled the synchronous context to reduce the confusion for a beginner user. Doing this would also prevent the code from being coupled to the storage backend (Because you won't need to use sync_to_async when using a Redis backend).
I see your point. How do you see expected changed to support this feature? I just do not see any obvious way to implement this.