Redirect back to previous page after logged in (Django)

Refresh

February 2019

Views

2.5k time

1

I have created login page forced login in several pages. Now i need to redirect back to previous page after successful login.

When i force login by @login_required(login_url='/login/'). It includes next parameter in query string.

enter image description here

I tried to catch it with redirect_to = request.REQUEST.get('next', '') and send it to redirect return HttpResponseRedirect(redirect_to) but didn't work.

view.py

def login(request):
    def errorHandle(error):
        form = LoginForm()
        return render_to_response('login/login.html', {
            'error' : error,
            'form' : form,
            })
    if request.method == 'POST': # If the form has been submitted...
        form = LoginForm(request.POST) # A form bound to the POST data
        if form.is_valid(): # All validation rules pass
            username = request.POST['username']
            password = request.POST['password']
            redirect_to = request.REQUEST.get('next', '')
            user = authenticate(username=username, password=password)
            if user is not None:
                if user.is_active:
                    # Redirect to a success page.
                    auth_login(request, user)
                    return HttpResponseRedirect(redirect_to)
#                    return render_to_response('login/logged_in.html', {
#                        'username': username,
#                        })
                else:
                    # Return a 'disabled account' error message
                    error = u'Account Disabled'
                    return errorHandle(error)
            else:
            # Return an 'invalid login' error message.
                error = u'Invalid Login'
                return errorHandle(error)
        else:
            error = u'Form is Invalid'
            return errorHandle(error)
    else:
        form = LoginForm() # An unbound form
        return render_to_response('login/login.html', {
            'form': form,
            })

template

<div id="login_form">
<form action="." method="post">
    {{ form.as_p }}
    <input type="submit" value="Login">
</form>
</div>

EDIT - I found the issue. It was problem with my template. This form below works fine.

    <form action="" method="post">
        <label for="username">User name:</label>
        <input type="text" name="username" value="" id="username">
        <label for="password">Password:</label>
        <input type="password" name="password" value="" id="password">

        <input type="submit" value="Login" id="button"/>
        <input type="hidden" name="next" value="{{ next|escape }}" />
    </form>

1 answers

3

You could just add this to the form:

<input type="hidden" value="{% if request.REQUEST.next %}{{ request.REQUEST.next }}{% else %}{% if request.META.HTTP_REFERER %}{{ request.META.HTTP_REFERER }}{% else %}/{% endif %}{% endif %}" name="next" />

Here are the cases it addresses:

  1. If the user comes from a login_required view: next is set by login_required
  2. If the user comes from the login form (ie. authentication did not pass): next=the previously set next value
  3. If the user comes from a non login_required view: next=the referer url
  4. If the user directly opened the login page: next=/

Note that this works with external login views too, which you should use.

As a goodie, here is part of my logout template, that redirects the user to the page he was before logging out.

{% block body %}
    <p>{% trans "You've been logged out." %}</p>
    {% if '/account/logout/' not in request.META.HTTP_REFERER %}
    <p>
        {% trans 'You will be redirected in a second' %}
    </p>
    {% endif %}
{% endblock %}

{% block extra_body %}
    {% if '/account/logout/' not in request.META.HTTP_REFERER %}
        <script type="text/javascript">
        document.location.href = '{{ request.META.HTTP_REFERER }}';
        </script>
    {% endif %}
{% endblock %}

I would like to thank the great startup that hired me sports pick, tipster social network because they allow me to 0) share the code and 1) use some of my time to help others. But the real reason I link it is so that you can test it. If this code doesn't work for you like it works there then you have another problem.