30

I'm trying to redirect users to custom url "/gallery/(username)/" after successfully logging in. It currently redirects to the default "/account/profile/" url While I know what I can override the redirect url in my settings.py, my url is dynamic thus it will not work.

Documentation states that I need to use the "next" parameter and context processors. I have the {{next}} in my template, but I'm confused on how to actually pass the "/gallery/(username)". Any help would be greatly appreciated.

p.s: I'm trying to steer away from writing my own login view.

Deesha
  • 538
  • 8
  • 27
django-d
  • 2,210
  • 3
  • 23
  • 41

6 Answers6

45

Django's login view django.contrib.auth.views.login accepts a dictionary named extra_context. The values in the dictionary are directly passed to the template. So you can use that to set the next parameter. Once that is done, you can set a hidden field with name next and value {{ next }} so that it gets rendered in the template.

Guruprasad
  • 1,447
  • 4
  • 16
  • 34
  • @django-d This should solve your requirement as it did for mine – Guruprasad Jun 07 '11 at 06:24
  • i tried this but it seemed to me that this would statically set next without the ability to override from within a referring view if needed. however, this greatly broadened my understanding of how django works and might be a simple and direct approach, thanks! – antiplex May 23 '13 at 07:44
24

I confess I usually use 2 redirects in order to get something like this to work.

First, Make your own registration/login.html page. You can copy-and-paste the html example in this section of the authentication docs to make the process a little easier. Instead of using the dynamic '{{ next }} variable from the context, however, hardwire the value of next to go to a generic landing view of logged-in users

<input type="submit" value="login" />
<input type="hidden" name="next" value="/gallery/" />

Then, in the view that you map to the /gallery/ URL, extract the User object from the request (since the user will now be logged in, especially if the gallery view is wrapped in a @permission_required or @login_required decorator. Use that view to redirect to the appropriate user-specific gallery page:

@login_required
def gallery(request):
    url = '/gallery/%s/' % request.user.username
    return HttpResponseRedirect(url)
Derek Adair
  • 21,846
  • 31
  • 97
  • 134
Jarret Hardie
  • 95,172
  • 10
  • 132
  • 126
  • 3
    I would say this is one `redirect` not two, which runs in the gallery view. Nice. – Timo Mar 06 '18 at 20:23
9

If you already have the custom template for login form you need to add the following inside your <form> tag:

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

BTW, you don't have to create your own login view. django.contrib.auth.views.login works fine. You only need to create a template for it (registration/login.html)

Andrey Fedoseev
  • 5,222
  • 1
  • 24
  • 19
  • 1
    This is exactly how I have it set up, but where exactly do I assign the value for "next". And how do I specify a dynamic value for "next". – django-d Aug 09 '10 at 15:59
  • I see now, you want a username in {{next}} and you don't know it before the form is submitted. In that case you have to create your own login view. Another option is to use a little of Javascript to fill the 'next' field right before the form is submitted. – Andrey Fedoseev Aug 09 '10 at 16:02
  • Man, question not about what. – Denis Jan 29 '13 at 10:01
  • This worked for me. I just had to add the hidden input tag inside my form. – Rupin Oct 17 '19 at 06:11
6

being an newbie to django and stumbling over this somewhat older thread i found a differing solution for the problem of dynamically (=override a custom default only if needed) setting the next-param that i'd like to share (working fine with django 1.5, earlier versions untested):

just as django-d i wanted avoid repetition and a custom login-view, so i used the stock django.contrib.auth.views.login-view by adding the line of

url(r'^login/$', 'django.contrib.auth.views.login', {'template_name': 'myapp/login.html',}, name='login'),

to my urls.py and within the login.html-templates form-element:

{% if not next or not next.strip %}
  {# avoid django.contrib.auth.views.login s default of /account/profile/ #}
  {% url 'afterlogindefaultview' as next %}
{% endif %}
<input type="hidden" name="next" value="{{ next }}" />

which to my understanding follows the decoupling-practice of the url-configurations from the views. so for views that should redirect to my apps login and afterwards head to a non-default view i use

return HttpResponseRedirect('%s?next=%s' % (reverse('login'), reverse('mycustomnext')) )

from the view where i want to have the user to log in. i use this to get back to the view where i left off for logging the user in.

antiplex
  • 938
  • 2
  • 12
  • 17
2

You can use a static redirect to /loggedin/ and then associate the url to a view that makes the correct redirect.

Login takes an extra step but if you want to use django's view it does the job.

naw
  • 1,496
  • 12
  • 13
0

create your own view for logging in, with it's own url, don't use the admin's one. you can store the next page in the session, or pass it as a GET parameter to the login view (i.e. /login?next=gallery) just don't forget to sanitize and validate that value before redirecting to it.

ozk
  • 2,025
  • 1
  • 15
  • 11
  • I really don't want to create a custom login view, but even if I did your example doesn't show how to pass the username. How Is "/login?next=gallery" supposed to automatically redirect to /gallery/username. Also where am I supposed to place "/login?next=gallery" within the URLconf or within the view using a regex? – django-d Aug 09 '10 at 15:53
  • 1
    the username is available in the session data. the URLconf part maps '/login' to your view. the ?next=gallery will be available in your view in request.GET['next'] – ozk Aug 09 '10 at 16:04