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' ДО перехода на страницу профиля. Однако, к своему удивлению, я обнаружил, что, похоже:
- I can't set a breakpoint in the adaptor (it is ignored)
- 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
).