I'm migrating an existing WSGI server to ASGI and I'm running into a problem where ORM usage in path converters raises a SynchronousOnlyOperation exception.
My converter code is something like this
class ModelPkConverter:
regex = r'\d+'
model = MyModel
def to_python(self, primary_key):
try:
return self.model.objects.get(pk=primary_key)
except self.model.DoesNotExist:
raise ValueError
def to_url(self, instance):
return f'{instance.pk}'
So when I go to a URL like /myapp/<MyModel:my_model>/
I get
django.core.exceptions.SynchronousOnlyOperation: You cannot call this from an async context - use a thread or sync_to_async.
Where exactly am I supposed to put sync_to_async
? If I do it in the converter like this
@sync_to_async
def to_python(self, primary_key):
...
The converter outputs a coroutine object instead of a MyModel instance so I get AttributeError when I attempt to use it.
AttributeError: 'coroutine' object has no attribute 'my_attribute'
Am I supposed to await
it in the view? That would defeat the purpose of using converters. I can just do get_object_or_404
instead.
Is there a solution that doesn't involve setting DJANGO_ALLOW_ASYNC_UNSAFE
to True?
At this point, I'm considering refactoring everything away from the converters and using <int:mymodel_id>
everywhere instead. Is there another way?