1 | | All the standard django middleware is marked as async-capable. As I understand that means that sync_to_async adapters will not be used if no other middleware is present. |
2 | | |
3 | | However, if you call an endpoint that is handled by an async view, somehow the adapters are still used, and middleware is executed in a separate thread. |
4 | | |
5 | | Moreover, if you add your custom middleware that is async_capable than it tries not to use adapters, and quickly fails: |
6 | | |
7 | | [[https://code.djangoproject.com/attachment/ticket/33716/bug.png]] |
| 1 | Here is what we have in MiddlewareMixin: |
10 | | AttributeError: 'coroutine' object has no attribute 'get' |
| 4 | def _async_check(self): |
| 5 | """ |
| 6 | If get_response is a coroutine function, turns us into async mode so |
| 7 | a thread is not consumed during a whole request. |
| 8 | """ |
| 9 | if asyncio.iscoroutinefunction(self.get_response): |
| 10 | # Mark the class as async-capable, but do the actual switch |
| 11 | # inside __call__ to avoid swapping out dunder methods |
| 12 | self._is_coroutine = asyncio.coroutines._is_coroutine |
| 13 | else: |
| 14 | self._is_coroutine = None |
17 | | Is reproduced in thae main branch and in 4.0 |
| 21 | |
| 22 | {{{ |
| 23 | def MyMiddleware(get_response): |
| 24 | |
| 25 | def middleware(request): |
| 26 | # Do some stuff with request that does not involve I/O |
| 27 | request.vip_user = True |
| 28 | return get_response(request) |
| 29 | |
| 30 | return middleware |
| 31 | |
| 32 | MyMiddleware.async_capable=True |
| 33 | }}} |
| 34 | |
| 35 | middleware(request) will return the response in sync case and a coroutine in the async case, despite being a regular function (because get_response is a coroutine function in the latter case). |
| 36 | |
| 37 | So I propose to remove the redundant _async_check |
| 38 | |
| 39 | Github project to see the error: https://github.com/pwtail/django_bug |