tags:

views:

3800

answers:

7

Hey,

I'm trying to build a simple website with login functionality very similar to the one here on SO. The user should be able to browse the site as an anonymous user and there will be a login link on every page. When clicking on the login link the user will be taken to the login form. After a succesfull login the user should be taken back to the page from where he clicked the login link in the first place. I'm guessing that I have to somehow pass the url of the current page to the view that handles the login form but I can't really get it to work. Maybe you guys could help me.

Thanks,

joerg

EDIT: I figured it out. I linked to the login form by passing the current page as a GET parameter and then used 'next' to redirect to that page. Thanks!

EDIT 2: My explanation did not seem to be clear so as requested here is my code: Lets say we are on a page foo.html and we are not logged in. Now we would like to have a link on foo.html that links to login.html. There we can login and are then redirected back to foo.html. The link on foo.html looks like this:

      <a href='/login/?next={{ request.path }}'>Login</a>

Now I wrote a custom login view that looks somewhat like this:

def login_view(request):
   redirect_to = request.REQUEST.get('next', '')
   if request.method=='POST':
      #create login form...
      if valid login credentials have been entered:
         return HttpResponseRedirect(redirect_to)  
   #...
   return render_to_response('login.html', locals())

And the important line in login.html:

<form method="post" action="./?next={{ redirect_to }}">

So yeah thats pretty much it, hope that makes it clear.

+5  A: 

Django's built-in authentication works the way you want.

Their login pages include a next query string which is the page to return to after login.

Look at http://docs.djangoproject.com/en/dev/topics/auth/#django.contrib.auth.decorators.login_required

S.Lott
Well, the login_required decorator would work just fine as it sets 'next' to whatever page I come from, but when using the decorator anonymous users cant view the site because they will be redirect to the login form right away. I think I just need to figure out how to set the value of 'next' to the url of the page the user comes from.
jörg
A: 

See django docs for views.login(), you supply a 'next' value (as a hidden field) on the input form to redirect to after a successful login.

YHVH
Yes but how do I actually set 'next' to the page I come from?
jörg
A: 

I linked to the login form by passing the current page as a GET parameter and then used 'next' to redirect to that page. Thanks!

jörg
+5  A: 

This may not be a "best practice", but I've successfully used this before:

return HttpResponseRedirect(request.META.get('HTTP_REFERER','/'))
Grant
This has a weak point - some users/browsers have passing referer turned off
Tomasz Zielinski
+1  A: 

Joerg, please, put source code here as an example, I can not imagine what you said :(. Thanks in advance.

Jano

+5  A: 

You do not need to make an extra view for this, the functionality is already built in.

First each page with a login link needs to know the current path, and the easiest way is to add the request context preprosessor to settings.py (the 4 first are default), then the request object will be available in each request:

settings.py:

TEMPLATE_CONTEXT_PROCESSORS = (
    "django.core.context_processors.auth",
    "django.core.context_processors.debug",
    "django.core.context_processors.i18n",
    "django.core.context_processors.media",
    "django.core.context_processors.request",
)

Then add in the template you want the Login link:

base.html:

<a href="{% url django.contrib.auth.views.login %}?next={{request.path}}">Login</a>

This will add a GET argument to the login page that points back to the current page.

The login template can then be as simple as this:

registration/login.html:

{% block content %}
<form method="post" action="">
  {{form.as_p}}
<input type="submit" value="Login">
</form>
{% endblock %}
sverrejoh
A: 

I encountered the same problem. This solution allows me to keep using the generic login view:

urlpatterns += patterns('django.views.generic.simple',
    (r'^accounts/profile/$', 'redirect_to', {'url': 'generic_account_url'}),
)
orlandu63