Hello all!
I am having a hard time implementing the following in a async CBV:
EDIT: more generally, what is considered a good way to use LoginRequiredMixin
and UserPassesTestMixin
in an async context?
class NewView(UserLoggedInMixin, FormView):
# normal FormView stuff
and the mixin (heavily WIP as you might guess… :)):
from asgiref.sync import sync_to_async
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.shortcuts import redirect
from django.core.exceptions import PermissionDenied
from django.urls import reverse_lazy
class UserLoggedInMixin(LoginRequiredMixin, UserPassesTestMixin):
async def dispatch(self, request, *args, **kwargs):
user = await request.auser()
if not user.is_authenticated:
return await self.handle_no_permission()
return await super().dispatch(request, *args, **kwargs)
@sync_to_async
def test_func(self):
user = self.request.user()
return user.is_active
# @sync_to_async
async def handle_no_permission(self):
if self.raise_exception:
raise PermissionDenied(self.get_permission_denied_message())
return await redirect(self.get_login_url())
@sync_to_async
def get_login_url(self):
user = self.request.user()
redir = reverse_lazy('login:index')
if self.request.path and self.request.resolver_match:
redir = f'{redir}?next={self.request.path}'
return redir
and the exception is this, whic to be honest I have a hard time getting my head around
TypeError at /xxx/xxx
argument of type 'coroutine' is not iterable
Request Method: GET
Request URL: http://127.0.0.1/xxx/xxx
Django Version: 5.0.3
Python Version: 3.11.6
Installed Applications:
['django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'mathfilters',
...]
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware']
Traceback (most recent call last):
File "/home/dil/env/lib/python3.11/site-packages/django/shortcuts.py", line 180, in resolve_url
return reverse(to, args=args, kwargs=kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/dil/env/lib/python3.11/site-packages/django/urls/base.py", line 88, in reverse
return resolver._reverse_with_prefix(view, prefix, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/dil/env/lib/python3.11/site-packages/django/urls/resolvers.py", line 851, in _reverse_with_prefix
raise NoReverseMatch(msg)
^^^^^^^^^^^^^^^^^^^^^^^^^
During handling of the above exception (Reverse for '<coroutine object SyncToAsync.__call__ at 0x7faff2c43740>' not found. '<coroutine object SyncToAsync.__call__ at 0x7faff2c43740>' is not a valid view function or pattern name.), another exception occurred:
File "/home/dil/env/lib/python3.11/site-packages/django/core/handlers/exception.py", line 42, in inner
response = await get_response(request)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/dil/env/lib/python3.11/site-packages/django/core/handlers/base.py", line 253, in _get_response_async
response = await wrapped_callback(
File "/home/dil/web/portal/web/auth/mixins.py", line 22, in dispatch
return await self.handle_no_permission()
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/dil/web/portal/web/auth/mixins.py", line 39, in handle_no_permission
return await redirect(self.get_login_url())
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/dil/env/lib/python3.11/site-packages/django/shortcuts.py", line 49, in redirect
return redirect_class(resolve_url(to, *args, **kwargs))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/dil/env/lib/python3.11/site-packages/django/shortcuts.py", line 186, in resolve_url
if "/" not in to and "." not in to:
^^^^^^^^^^^^^
Exception Type: TypeError at /post/new
Exception Value: argument of type 'coroutine' is not iterable
Any ideas?