3

If i user is not logged in and encounters a @login_required decorator, it will be send to my login_user view. after login it will be send to my index. how can I my redirect to the previous page.

def login_user(request):
    login_form = LoginForm(request.POST or None)
    if request.POST and login_form.is_valid():
        user = login_form.login(request)
        if user:
            login(request, user)
            if request.POST['next'] != "":
                return HttpResponseRedirect(request.POST['next'])
            else:
                return HttpResponseRedirect(reverse('index'))

    #return render(request, 'login.html', {'login_form': login_form })
    return render_to_response('login.html', {'login_form': login_form}, context_instance=RequestContext(request))

now i have been looking at: Django: Redirect to previous page after login But I'm not sure how to use this, since I don't sent them to login with a link but with a decorator

Community
  • 1
  • 1
Hans de Jong
  • 2,030
  • 6
  • 35
  • 55
  • have that included in the login template inside the login form – Hans de Jong Apr 10 '14 at 12:06
  • edditing your post to reflect the solution is very good, but better do it in a second codeblock, so people can compare wrong code with right code. I'll upvote your question if you do it :-) – tike Apr 10 '14 at 12:29

2 Answers2

7

the login_required decorator annotates the login-url adding a next field to the GET parameters. see login_required.

e.g. if LOGIN_URL is /login it becomes /login?next=/polls/3/vote

This gets passed to your login view, where you use it

  1. To render the login page upon GET or errorneos POST in a request aware manner. Please note that you need to pass the request variables to the template rendercontext. see RequestContext and render_to_response.

    return render_to_response(
            'login.html',
            my_data_dictionary,
            context_instance=RequestContext(request)
    )
    
  2. in the template add a line like this to the login form

    <input type="hidden" name="next" value="{{ next }}">
    
  3. Finally upon a succesfull POST use this value to HttpResponseRedirect, either to the value of next or to LOGIN_REDIRECT_URL if no next value is present. see HttpResponseRedirect.

    ... user was succesfully authenticated...
    if request.POST["next"] is Not "":
        HttpResponseRedirect(request.POST["next"])
    else:
        HttpResponseRedirect(settings.LOGIN_REDIRECT_URL)
    

I hope this clarifies things a little bit.

tike
  • 2,234
  • 17
  • 19
  • Right! veto up, that's just what I want to say – WeizhongTu Apr 10 '14 at 11:28
  • Thanks, i think i grasp the concept better now, and indeed why i get redirected to my login, i get for example: /login/?next=/admin/item/create/ but now im not sure how i give {{ next }} the value /admin/item/create/ (still going to my login_redirect_url) aslo what is the con of using the render(request, "") shortcut? – Hans de Jong Apr 10 '14 at 11:35
  • 1
    it is done automatically by the `login_required` decorator, just because it's there. Welcome to django magic ;-) – tike Apr 10 '14 at 11:36
  • now i think am a step closer, added the code and hiddne field. but somehow my {{ next }} is always empty (checked with trying to print it) – Hans de Jong Apr 10 '14 at 11:42
  • as I said in the answer: use `RequestContext` to pass the request variables to your template upon rendering, see the link at the end of the answer. – tike Apr 10 '14 at 11:53
  • okay I will try tho render should force a requestcontext as far as i understood render() (from django documentation: render() is the same as a call to render_to_response() with a context_instance argument that forces the use of a RequestContext.) – Hans de Jong Apr 10 '14 at 11:59
  • I also recommend you use `django-debug-toolbar` while developing, it saves you a lot of time in such cases. – tike Apr 10 '14 at 12:04
  • i will take a look at the debugger, thanks for the suggestion (and the help) – Hans de Jong Apr 10 '14 at 12:15
  • 1
    It's not a debugger. It adds a toolbar to your website (while `settings.DEBUG` is `True`). It displays the full rendering context, template paths searched, db queries executed, etc. This saves you from writing debug statements just to check if a context variable is there and what it's value is. – tike Apr 10 '14 at 12:18
1

I got it to work doing the following:

def login_user(request):
    login_form = LoginForm(request.POST or None)

    if request.POST and login_form.is_valid():
        user = login_form.login(request)
        if user:
            login(request, user)
            return HttpResponseRedirect(request.POST.get('next', reverse('index')))

    return render(request, 'login.html', {'login_form': login_form, 'next': request.GET.get('next', '') })
    #return render_to_response('login.html', {'login_form': login_form, 'next': request.GET.get('next', '')}, context_instance=RequestContext(request))

also included

<input type="hidden" name="next" value="{{ next }}">

in my login.html login_form

Hans de Jong
  • 2,030
  • 6
  • 35
  • 55