Django allauth с пользовательским адаптером перенаправления, игнорирующим параметр "?next"

Я использую Django 3.2 и django-allauth 0.44

У меня есть пользовательский адаптер, который перенаправляет пользователя на страницу его профиля при входе в систему - однако я также хочу иметь возможность использовать ?next=/some/url/, чтобы пользователь перенаправлялся на этот url, если в аргументах next есть параметр GET.

Это мой пользовательский адаптер:

class MyAccountAdapter(DefaultAccountAdapter):
    def get_login_redirect_url(self, request):
        print(f"GET request dict is {request.GET}")
        return reverse('profile', kwargs={'username': request.user.username})  

Мне нужно изменить мой пользовательский адаптер, чтобы он проверял наличие GET-параметра 'next' ДО перехода на страницу профиля. Однако, к своему удивлению, я обнаружил, что, похоже:

  1. I can't set a breakpoint in the adaptor (it is ignored)
  2. If I deliberately introduce an error in the adaptor (e.g. print(request.GET['hello']) ) the code runs fines and redirects to the profile page without throwing an exception

Как я могу использовать ?next=/some/url с django-allauth, используя при этом пользовательский адаптер?

Во-первых, ваш первоначальный код для адаптера (из ревизии 1 вопроса) был правильным:

class MyAccountAdapter(DefaultAccountAdapter):
    def get_login_redirect_url(self, request):
        print(f"GET request dict is {request.GET}")
        return reverse('profile', kwargs={'username': request.user.username})

Проблема в том, что вы не установили настройку ACCOUNT_ADAPTER.

Далее, как вы говорите, ваш url выглядит как /accounts/login/?next=https://127.0.0.1:8000/&page=2, проблема в том, что ваш redirect url является абсолютным url с именем хоста, но allauth передает allowed_hosts=None в функцию, которая проверяет безопасность этого url, в результате чего он не может быть использован. Решением этой проблемы является либо использование относительных урлов, либо редактирование вашего адаптера для разрешения определенных имен хостов:

class MyAccountAdapter(DefaultAccountAdapter):
    def get_login_redirect_url(self, request):
        print(f"GET request dict is {request.GET}")
        return reverse('profile', kwargs={'username': request.user.username})
    
    def is_safe_url(self, url):
        try:
            from django.utils.http import url_has_allowed_host_and_scheme
        except ImportError:
            from django.utils.http import (
                is_safe_url as url_has_allowed_host_and_scheme,
            )

        return url_has_allowed_host_and_scheme(url, allowed_hosts={'127.0.0.1:8000'}) # add any other hostname you might want to allow redirects to

Далее ваша строка запроса выглядит следующим образом: ?next=/&page=2 Здесь проблема в том, что у вас есть &, который используется для разделения параметров строки запроса. Хотя вы говорите, что это работает, заменив его на ?, в идеале вы также должны urlencode его, чтобы ваша строка запроса стала ?next=/%3Fpage%3D2 (? заменен на %3F и = заменен на %3D).

Вернуться на верх