TLDR: <input type="hidden" name="next" value="{{ next }}">
is the line of code I don't understand. With it this system of redirecting works fine, however, I do not understand what it is doing. It's as if is linking the user to the next page but no link is actually clicked?
I understand that if a user is not logged in the next
parameter is used to redirect the user to whatever @login_required
decorated view they were trying to access after logging in. Though the way this happens seems a bit automagical.
I have the following login related settings:
LOGIN_REDIRECT_URL = 'dashboard' # tells django which url to redirect after login if no 'next' parameter is present in the request
LOGIN_URL = 'login' # url to redirect the user to log in (for example, views using the login_required decorator)
and am using the authentication views fount in django.contrib.auth
(only included three for simplicity):
from django.urls import path
from . import views
from django.contrib.auth import views as auth_views
urlpatterns = [
path('', views.dashboard, name = 'dashboard'),
path('login/', auth_views.LoginView.as_view(), name = 'login'),
path('password_change/', auth_views.PasswordChangeView.as_view(), name = 'password_change'),
]
Here is the custom login.html tempate located at account/registration/index.html:
<div class="login-form">
<form action="{% url 'login' %}" method="post">
{{ form.as_p }}
{% csrf_token %}
<input type="hidden" name="next" value="{{ next }}">
<input type="submit" name="" value="Log-in">
</form>
</div>
Now say I am not logged in and try to access /account/password_change
, I will be redirected to the login
view and the path will be http://127.0.0.1:8000/account/login/?next=/account/password_change/
, after logging in I can change my password with no problem. However, If I remove <input type="hidden" name="next" value="{{ next }}">
from index.html:
<div class="login-form">
<form action="{% url 'login' %}" method="post">
{{ form.as_p }}
{% csrf_token %}
<input type="submit" name="" value="Log-in">
</form>
</div>
and again try to access /account/change_password
(as a non logged in user), I will be redirected to the login page and the url will be the same as before http://127.0.0.1:8000/account/login/?next=/account/password_change/
. However, when I login this time I am redirected to the dashboard
view (this makes sense to me, I defined this with LOGIN_REDIRECT_URL = 'dashboard'
and did not provide a next
parameter.
With all that said, what I don't understand is why after removing <input type="hidden" name="next" value="{{ next }}">
is the path at the login
view sill http://127.0.0.1:8000/account/login/?next=/account/password_change/
(even though I will be redirect to dashboard
and not password_change
)? And why after adding <input type="hidden" name="next" value="{{ next }}">
back to the html does the browser know how to redirect the user to the correct page?
If anyone takes the time to read and respond to this, thanks in advance!
Nice question. Please read this code segment https://github.com/django/django/blob/master/django/contrib/auth/views.py#L71
If you observe closely, this line of code is trying to get data from POST
as name next
. If there is no key named next
, it tries to get value from query parameter; I mean GET.
So, if we remove input from form (<input type="hidden" name="next" value="{{ next }}">
), it still works as query params are acting as fallback.
Hope, it helps.