tmbo/questionary

Call async prohibed method in validate function

AMontagu opened this issue · 0 comments

Describe the problem

Whant to use a simple validation class like this:

class CaseNumberValidator(Validator):
    def validate(self, case_number):
        if Case.objects.filter(case_number=case_number.text).exists():
            raise ValidationError(
                message="Case with this case number already exist",
                cursor_position=len(case_number.text),
            )

But I am getting the error:

 File "/opt/code/atlas/management/commands/import_for_dev.py", line 22, in validate
    if Case.objects.filter(case_number=case_number.text).exists():
  File "/usr/local/lib/python3.8/site-packages/django/db/models/query.py", line 1225, in exists
    return self.query.has_results(using=self.db)
  File "/usr/local/lib/python3.8/site-packages/django/db/models/sql/query.py", line 592, in has_results
    return compiler.has_results()
  File "/usr/local/lib/python3.8/site-packages/django/db/models/sql/compiler.py", line 1363, in has_results
    return bool(self.execute_sql(SINGLE))
  File "/usr/local/lib/python3.8/site-packages/django/db/models/sql/compiler.py", line 1393, in execute_sql
    cursor = self.connection.cursor()
  File "/usr/local/lib/python3.8/site-packages/django/utils/asyncio.py", line 24, in inner
    raise SynchronousOnlyOperation(message)

This is normal as db call in django are synchroous only.

Describe the solution

There is mutliple solutions.

First and simple is to do something like:

if asyncio.iscoroutinefunction(grpc_settings.ROOT_HANDLERS_HOOK):
    await grpc_settings.ROOT_HANDLERS_HOOK(server)
else:
    await sync_to_async(grpc_settings.ROOT_HANDLERS_HOOK)(server)

That enable us to choose to declare validate as async and then use sync_to_async utils from asgiref


Other one is to force the validate question in a sync context.


Finale one is to have two differente validation methode depending of the context

Alternatives considered

No response