1
0
mirror of https://github.com/django/django.git synced 2025-03-05 23:12:32 +00:00

Fixed #28216 -- Added next_page/get_default_redirect_url() to LoginView.

This commit is contained in:
ThinkChaos 2017-06-07 16:48:28 +02:00 committed by Mariusz Felisiak
parent 59841170ba
commit b99d6c9cbc
5 changed files with 67 additions and 6 deletions

View File

@ -43,6 +43,7 @@ class LoginView(SuccessURLAllowedHostsMixin, FormView):
""" """
form_class = AuthenticationForm form_class = AuthenticationForm
authentication_form = None authentication_form = None
next_page = None
redirect_field_name = REDIRECT_FIELD_NAME redirect_field_name = REDIRECT_FIELD_NAME
template_name = 'registration/login.html' template_name = 'registration/login.html'
redirect_authenticated_user = False redirect_authenticated_user = False
@ -63,8 +64,7 @@ class LoginView(SuccessURLAllowedHostsMixin, FormView):
return super().dispatch(request, *args, **kwargs) return super().dispatch(request, *args, **kwargs)
def get_success_url(self): def get_success_url(self):
url = self.get_redirect_url() return self.get_redirect_url() or self.get_default_redirect_url()
return url or resolve_url(settings.LOGIN_REDIRECT_URL)
def get_redirect_url(self): def get_redirect_url(self):
"""Return the user-originating redirect URL if it's safe.""" """Return the user-originating redirect URL if it's safe."""
@ -79,6 +79,10 @@ class LoginView(SuccessURLAllowedHostsMixin, FormView):
) )
return redirect_to if url_is_safe else '' return redirect_to if url_is_safe else ''
def get_default_redirect_url(self):
"""Return the default redirect URL."""
return resolve_url(self.next_page or settings.LOGIN_REDIRECT_URL)
def get_form_class(self): def get_form_class(self):
return self.authentication_form or self.form_class return self.authentication_form or self.form_class

View File

@ -47,6 +47,12 @@ Minor features
* The default iteration count for the PBKDF2 password hasher is increased from * The default iteration count for the PBKDF2 password hasher is increased from
260,000 to 320,000. 260,000 to 320,000.
* The new
:attr:`LoginView.next_page <django.contrib.auth.views.LoginView.next_page>`
attribute and
:meth:`~django.contrib.auth.views.LoginView.get_default_redirect_url` method
allow customizing the redirect after login.
:mod:`django.contrib.contenttypes` :mod:`django.contrib.contenttypes`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -996,17 +996,26 @@ implementation details see :ref:`using-the-views`.
See :doc:`the URL documentation </topics/http/urls>` for details on using See :doc:`the URL documentation </topics/http/urls>` for details on using
named URL patterns. named URL patterns.
**Attributes:** **Methods and Attributes**
.. attribute:: template_name .. attribute:: template_name
The name of a template to display for the view used to log the user in. The name of a template to display for the view used to log the user in.
Defaults to :file:`registration/login.html`. Defaults to :file:`registration/login.html`.
.. attribute:: next_page
.. versionadded:: 4.0
The URL to redirect to after login. Defaults to
:setting:`LOGIN_REDIRECT_URL`.
.. attribute:: redirect_field_name .. attribute:: redirect_field_name
The name of a ``GET`` field containing the URL to redirect to after The name of a ``GET`` field containing the URL to redirect to after
login. Defaults to ``next``. login. Defaults to ``next``. Overrides the
:meth:`get_default_redirect_url` URL if the given ``GET`` parameter is
passed.
.. attribute:: authentication_form .. attribute:: authentication_form
@ -1043,6 +1052,14 @@ implementation details see :ref:`using-the-views`.
<django.http.HttpRequest.get_host>`, that are safe for redirecting <django.http.HttpRequest.get_host>`, that are safe for redirecting
after login. Defaults to an empty :class:`set`. after login. Defaults to an empty :class:`set`.
.. method:: get_default_redirect_url()
.. versionadded:: 4.0
Returns the URL to redirect to after login. The default implementation
resolves and returns :attr:`next_page` if set, or
:setting:`LOGIN_REDIRECT_URL` otherwise.
Here's what ``LoginView`` does: Here's what ``LoginView`` does:
* If called via ``GET``, it displays a login form that POSTs to the * If called via ``GET``, it displays a login form that POSTs to the

View File

@ -52,8 +52,8 @@ class AuthViewsTestCase(TestCase):
cls.u1 = User.objects.create_user(username='testclient', password='password', email='testclient@example.com') cls.u1 = User.objects.create_user(username='testclient', password='password', email='testclient@example.com')
cls.u3 = User.objects.create_user(username='staff', password='password', email='staffmember@example.com') cls.u3 = User.objects.create_user(username='staff', password='password', email='staffmember@example.com')
def login(self, username='testclient', password='password'): def login(self, username='testclient', password='password', url='/login/'):
response = self.client.post('/login/', { response = self.client.post(url, {
'username': username, 'username': username,
'password': password, 'password': password,
}) })
@ -726,6 +726,31 @@ class LoginTest(AuthViewsTestCase):
self.login() self.login()
self.assertNotEqual(original_session_key, self.client.session.session_key) self.assertNotEqual(original_session_key, self.client.session.session_key)
def test_login_get_default_redirect_url(self):
response = self.login(url='/login/get_default_redirect_url/')
self.assertRedirects(response, '/custom/', fetch_redirect_response=False)
def test_login_next_page(self):
response = self.login(url='/login/next_page/')
self.assertRedirects(response, '/somewhere/', fetch_redirect_response=False)
def test_login_named_next_page_named(self):
response = self.login(url='/login/next_page/named/')
self.assertRedirects(response, '/password_reset/', fetch_redirect_response=False)
@override_settings(LOGIN_REDIRECT_URL='/custom/')
def test_login_next_page_overrides_login_redirect_url_setting(self):
response = self.login(url='/login/next_page/')
self.assertRedirects(response, '/somewhere/', fetch_redirect_response=False)
def test_login_redirect_url_overrides_next_page(self):
response = self.login(url='/login/next_page/?next=/test/')
self.assertRedirects(response, '/test/', fetch_redirect_response=False)
def test_login_redirect_url_overrides_get_default_redirect_url(self):
response = self.login(url='/login/get_default_redirect_url/?next=/test/')
self.assertRedirects(response, '/test/', fetch_redirect_response=False)
class LoginURLSettings(AuthViewsTestCase): class LoginURLSettings(AuthViewsTestCase):
"""Tests for settings.LOGIN_URL.""" """Tests for settings.LOGIN_URL."""

View File

@ -3,6 +3,7 @@ from django.contrib.auth import views
from django.contrib.auth.decorators import login_required, permission_required from django.contrib.auth.decorators import login_required, permission_required
from django.contrib.auth.forms import AuthenticationForm from django.contrib.auth.forms import AuthenticationForm
from django.contrib.auth.urls import urlpatterns as auth_urlpatterns from django.contrib.auth.urls import urlpatterns as auth_urlpatterns
from django.contrib.auth.views import LoginView
from django.contrib.messages.api import info from django.contrib.messages.api import info
from django.http import HttpRequest, HttpResponse from django.http import HttpRequest, HttpResponse
from django.shortcuts import render from django.shortcuts import render
@ -78,6 +79,11 @@ def login_and_permission_required_exception(request):
pass pass
class CustomDefaultRedirectURLLoginView(LoginView):
def get_default_redirect_url(self):
return '/custom/'
# special urls for auth test cases # special urls for auth test cases
urlpatterns = auth_urlpatterns + [ urlpatterns = auth_urlpatterns + [
path('logout/custom_query/', views.LogoutView.as_view(redirect_field_name='follow')), path('logout/custom_query/', views.LogoutView.as_view(redirect_field_name='follow')),
@ -149,6 +155,9 @@ urlpatterns = auth_urlpatterns + [
views.LoginView.as_view(redirect_authenticated_user=True)), views.LoginView.as_view(redirect_authenticated_user=True)),
path('login/allowed_hosts/', path('login/allowed_hosts/',
views.LoginView.as_view(success_url_allowed_hosts={'otherserver'})), views.LoginView.as_view(success_url_allowed_hosts={'otherserver'})),
path('login/get_default_redirect_url/', CustomDefaultRedirectURLLoginView.as_view()),
path('login/next_page/', views.LoginView.as_view(next_page='/somewhere/')),
path('login/next_page/named/', views.LoginView.as_view(next_page='password_reset')),
path('permission_required_redirect/', permission_required_redirect), path('permission_required_redirect/', permission_required_redirect),
path('permission_required_exception/', permission_required_exception), path('permission_required_exception/', permission_required_exception),