views:

40

answers:

1

Hello, I have a new question about django (I post a lost of them these days^^).

Here is my situation : I have a custom login view (registered as login url in the settings) where I authenticate the users. I chose to do a custom view to be able to add messages and logging.

The authentication works well, but I have a problem with the GET parameter 'next'. It is set automatically by the views redirecting the users for authentication. It is used in my view to redirect the user after a successful login.

Here is the code :

from django.http import HttpResponse
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect
from django.shortcuts import render_to_response
from django.utils.translation import ugettext as _
from django.contrib import messages
from django.template import RequestContext
from django.contrib.auth import authenticate, login, logout

import logging
logger = logging.getLogger("views")

def login_user(request):
    """
    Displays the login form or authenticates the user if called by POST.
    """
    accepted = False

    next = request.GET.get('next', None)

    if not request.user.is_authenticated():
        if request.POST:
            # Get the form data and check the user credentials
            username = request.POST['username']
            password = request.POST['password']
            user = authenticate(username=username, password=password)

            if user is not None:
                if user.is_active:
                    # Log the user in
                    login(request, user)
                    logger.info("Login of user : %s", user.username)

                    # Confirm the login
                    messages.success(request,_('Login successful. Welcome !'))
                    accepted = True
                else:
                    messages.error(request,_('This account has been disabled by the administrator.'))
            else:
                messages.warning(request,_('The given username or password is invalid. Please try again.'))
    else:
        # If already authenticated
        accepted = True

    # Choose where to go
    if accepted:
        return HttpResponse(next)
        if next:
            return HttpResponseRedirect(next)
        else:
            return HttpResponseRedirect(reverse('myview'))
    else:
        return render_to_response('login.html',
                                    context_instance=RequestContext(request))

The next parameter is correct when the user is accessing the login view when already authenticated (first else).

When an anonymous user tries to go to /editor/25 (for example) and is redirected to login for authentication, "next" is always None even if present in the url (it should be "/editor/25").

There should be one simple error somewhere. Maybe it has to do with authenticate() or login() (django.contrib.auth).

Thanks for your help.

+1  A: 

When an anonymous user tries to go to /editor/25 (for example) and is redirected to login for authentication, "next" is always None even if present in the url (it should be "/editor/25").

This sounds strange. Can you check that the URL indeed has ?next=/editor/25/ as the query string? Also log request.GET and see what turns up.

Also, you may want to pick up the next parameter from request.GET and include it as a (optional) hidden input in the form when rendering the template. The auth module's login view does this. This way your form can pick up next from request.POST on POST.

Manoj Govindan
It is really strange. I will try to log the request.GET and check the url tomorrow, I'm not at work now (Japan hours). What is the point of taking it from POST ? And actually I can't because the user is redirected to the page and the value is None. I can't find anything about this issue in the docs.
Marc Demierre
Now that I think about it you are probably right, the next is not submitted with the form and it explains why it does that only with users submitting the form (anonymous users)
Marc Demierre
It was it. Sorry about the question, I should have looked at the django source.
Marc Demierre