0

I have a very common problem - after login I want to redirect to the page where login was called. I can describe situation exactly like here: Django: Redirect to previous page after login

There are 2 options where you can log in - from the home page (which is defined in base.html) and from bokeh.html (other views inherit from bokeh)

my base.html and bokeh.html have the same block to redirect to login. Difference is, that login called from home page should return to home page and from other page should return to page where was called.

<li class="nav-item">
    <a class="nav-link" href="{% url 'login' %}">Login</a>
</li>

my login.html

<form method="POST">
{% csrf_token %}
<div class="form-group">
    <input type="text" class="form-control" placeholder="Enter Username" name="username" required>
</div>
<div class="form-group">
    <input type="password" class="form-control" placeholder="Enter Password" name="password" required>
</div>
<div class="form-group">
    <button type="submit" class="btn btn-dark">Login</button>
</div>
</form>

and views.py

def login(request):
    if request.method == 'POST':
        username = request.POST['username']
        password = request.POST['password']
        user = auth.authenticate(username=username,password=password)
        if user is not None:
            auth.login(request,user)
            return redirect('home')
        else:
            messages.info(request,'Invalid credentials')
            return redirect('login')
    else:
        return render(request,'login.html')

I was trying to add next to my form in login.html but it didn't work. While accessing to login from page other than home page it was like: localhost:8000/login?next=/bokeh/ and after submiting form I was still on login but URL changed to localhost:8000/login?next=. I know it's pretty hard to explain but I will add another information in need.

Frendom
  • 508
  • 6
  • 24

1 Answers1

1

First, change the template to include the urlencoded next parameter to the login url:

<li class="nav-item">
    <a class="nav-link" href="{% url 'login' %}?next={{ request.path |urlencode }}">Login</a>
</li>

Second, your login template needs to preserve the value of next:

<form method="POST">
<input type="hidden" name="next" value=""{{ next }}">
{% csrf_token %}
<div class="form-group">
    <input type="text" class="form-control" placeholder="Enter Username" name="username" required>
</div>
<div class="form-group">
    <input type="password" class="form-control" placeholder="Enter Password" name="password" required>
</div>
<div class="form-group">
    <button type="submit" class="btn btn-dark">Login</button>
</div>
</form>

Third, your login view should retrieve the URL parameter and pass it to the template:

from django.conf import settings

def login(request):
    if request.method == 'GET':
        next = request.GET.get('next', settings.LOGIN_REDIRECT_URL)
        return render(request, 'login.html', {'next': next})

    if request.method == 'POST':
        next = request.POST['next']
        username = request.POST['username']
        password = request.POST['password']
        user = auth.authenticate(username=username,password=password)
        if user is not None:
            auth.login(request,user)
            return redirect(next)
        else:
            messages.info(request,'Invalid credentials')
            return redirect('login')

Finally, you should consider using the Django Authentication Views instead of writing your own login views!

Jaap Joris Vens
  • 3,382
  • 2
  • 26
  • 42
  • Well it doesnt work as I would like. I mean, you have an access to login from every view of website. Now after login I want to go back to the site where this login was called (just to previous page). In this situation I still redirect to home page – Frendom Mar 23 '20 at 07:24
  • You're right, I forgot about the required change to the template code. I have updated my answer! – Jaap Joris Vens Mar 23 '20 at 11:00