Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Redirect to Next after login in Django

Tags:

django

login

When a user accesses a url which requires login. The view decorator redirects to the login page. after the user enters his username and password how can I redirect the user to the page he was trying to access ('next') ?

Views.py

def login_view(request):
    template = 'pos/login.html'
    form = LoginForm
    if request.method == 'POST':
        username = request.POST.get('username', '')
        password = request.POST.get('password', '')
        user = authenticate(username=username, password=password)
        if user is not None:
            if user.is_active:
                login(request, user)
                messages.success(request, "You have logged in!")
                return redirect('home')
            else:
                messages.warning(request, "Your account is disabled!")
                return redirect('/login')
        else:
            messages.warning(request, "The username or password are not valid!")
            return redirect('/login')
    context = {'form': form}
    return render(request, template, context)

@login_required(redirect_field_name='next', login_url='/login')
def bar(request):
    template = 'pos/bar.html'
    drink = OrderItem.objects.filter(product__catgory__gt=1).order_by('-created')
    context = {'drink': drink}
    return render(request, template, context)

Login.html

<form action="/login" id="login_form" method="post" class="form-signin">
    {% csrf_token %}
    {{ form.as_p }}
    <button class="btn btn-lg btn-primary btn-block" type="submit" value="login">Sign in</button>
    <input type="hidden" name="next" value="{{next}}" />
</form>

url.py

     url(r'^login', views.login_view, name='login'),

forms.py

class LoginForm(AuthenticationForm):
    username = forms.CharField(label="Username", required=True, max_length=30,
                           widget=forms.TextInput(attrs={
                               'class': 'form-control',
                               'name': 'username'}))
    password = forms.CharField(label="Password", required=True, max_length=30,
                           widget=forms.PasswordInput(attrs={
                               'class': 'form-control',
                               'name': 'password'}))
like image 692
Basel J. Hamadeh Avatar asked Jul 18 '16 07:07

Basel J. Hamadeh


4 Answers

You can try:

return redirect(self.request.GET.get('next'))
like image 176
Arun Ghosh Avatar answered Nov 14 '22 03:11

Arun Ghosh


The accepted answer does not check for the next parameter redirecting to an external site. For many applications that would be a security issue. Django has that functionality inbuilt in form of the django.utils.http.is_safe_url function. It can be used like this:

from django.shortcuts import redirect
from django.utils.http import is_safe_url
from django.conf import settings

def redirect_after_login(request):
    nxt = request.GET.get("next", None)
    if nxt is None:
        return redirect(settings.LOGIN_REDIRECT_URL)
    elif not is_safe_url(
            url=nxt,
            allowed_hosts={request.get_host()},
            require_https=request.is_secure()):
        return redirect(settings.LOGIN_REDIRECT_URL)
    else:
        return redirect(nxt)

def my_login_view(request):
    # TODO: Check if its ok to login.
    # Then either safely redirect og go to default startpage.
    return redirect_after_login(request)
like image 35
Rune Kaagaard Avatar answered Nov 14 '22 05:11

Rune Kaagaard


You can try by simply add this input field before submit button in accounts/login.html template

<input type="hidden" name="next" value="{{ request.GET.next }}"/>
like image 34
Sandhya Kumari Avatar answered Nov 14 '22 04:11

Sandhya Kumari


Passing next to the login form and then the form passing that value on to view in a hidden input can be a bit convoluted.

As an alternative, it's possible to use django.core.cache here.

This way there is no need to pass anything extra to the form or to give the form an extra input field.

def login_view(request):
    if request.method == 'GET':
        cache.set('next', request.GET.get('next', None))

    if request.method == 'POST':
        # do your checks here

        login(request, user)

        next_url = cache.get('next')
        if next_url:
            cache.delete('next')
            return HttpResponseRedirect(next_url)

    return render(request, 'account/login.html')
like image 37
M3RS Avatar answered Nov 14 '22 03:11

M3RS