0

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?

Konstantin K.
  • 335
  • 2
  • 6
  • 1
    I am not sure whether this can be made to work, but the approach is kinda weird. I would recommend against it, the converters are probably only designed to handle simple operations like string parsing. So I would go with `get_object_or_404` – Alexandr Tatarinov Jun 19 '21 at 18:51
  • That seems to be the way to go. I'll move away from using converters this way. Thanks. – Konstantin K. Jun 19 '21 at 20:03

0 Answers0