6

I have a custom login url/view/template. I use the @login_required decorator for a page (let 's call it my_page) that requires login. Attempting to access

my_site.com/my_page 

correctly calls

my_site.com/login/?next=/my_page/ 

BUT my view is unable to parse out the value of ?next=/my_page/my and instead always redirects to my default which is /qa/ in my view:

def login_with_email(request):
    error = ''
    if request.method == 'POST':
        if not request.POST.get('email', ''):
            error = 'Please enter your email and password'
        if not request.POST.get('password', ''):
            error = 'Please enter your email and password'    
        if not error:    
            email = request.POST['email']
            password = request.POST['password']

            try:
                user = User.objects.get(email=email)
                user = authenticate(username=user.username, password=password)
                if user is not None:
                    if user.is_active:
                        login(request, user)

                        # *** 
                        next_page = request.GET.get('next', '/qa/')
                        response = HttpResponseRedirect(next_page)
                        # ***

                        response.set_cookie('login_email', email, max_age=14*24*60*60)
                        return response
            except User.DoesNotExist:    
                error = 'Invalid email and password combination'

Urls.py:

url(r'^login/$', views.login_with_email), 
Tom Leys
  • 18,473
  • 7
  • 40
  • 62
user2916527
  • 529
  • 4
  • 17
  • Please show your `urls.py`. – alecxe Jan 10 '14 at 19:30
  • possible duplicate of [Capturing url parameters in request.GET](http://stackoverflow.com/questions/150505/capturing-url-parameters-in-request-get) – niekas Jan 10 '14 at 19:33
  • @niekas: Don't think so. I looked at that Q&A. I may be wrong, but I believe I followed the instructions correctly using request.GET.get. – user2916527 Jan 10 '14 at 19:46
  • looks like you are logged in. – karthikr Jan 10 '14 at 20:46
  • 1
    is your code above indented correctly? i.e. the `try` block is inside the `if not error` block and everything is inside the `if request.method == 'POST'` block? because if Django just redirected to your view it wouldn't have been a POST request – Anentropic Jan 10 '14 at 20:47
  • I figured it out. I needed to use request.GET.get to get the value from the url since at that point request.method==GET and pass it my template (where I store it as a hidden field) and then access it in my view once request.method == POST. I have revised the view above with the working code and added my template code. – user2916527 Jan 10 '14 at 21:42
  • 1
    Now that it's solved, I'd recommend answering your own question, as it still shows as unanswered in search. For more info, see http://stackoverflow.com/help/self-answer. – Joe Tricarico May 16 '14 at 19:48

1 Answers1

1

Per my comment below, I realized I had to grab the value of next from the url before my POST processing (thanks to @Anentropic for flashing on the lightbulb). So now I grab the value of next, pass it to my template where I store it in a hidden field, and finally access it when required for the redirect using request.POST.get:

Revised view:

def login_with_email(request):
    error = ''
    next = request.GET.get('next', '/qa/profile/private/')
    if request.method == 'POST':
    ...
                if user.is_active:
                    login(request, user)
                    next = request.POST.get('next', '/qa/profile/private/')
                    ...    
    return render(request, 'qa/login_with_email.html', {'error': error, 'login_email': login_email, 'next': next,})

And in my template:

<form method="post" action="." autocomplete="on">{% csrf_token %} 
    <p><input type="hidden" name="next" value="{{ next }}"/></p>
    ...

Note: This answer was originally posted by the poser of the question. I just moved it here.

Tom Leys
  • 18,473
  • 7
  • 40
  • 62