Redirect User to another url with django-allauth log in signal
Asked Answered
R

4

27

I am using Django-allauth for my login/signup related stuff, so when a user signs up(first time) into my site, I am redirecting him to /thanks/ page by defining below setting in settings.py file

LOGIN_REDIRECT_URL = '/thanks/'

But when the user tried to log in for the next time(if already registered) I should redirect him to '/dashboard/' URL

So tried to alter that with Django-allauth signals like below which is not working at all

@receiver(allauth.account.signals.user_logged_in)
def registered_user_login(sender, **kwargs):
    instance = User.objects.get_by_natural_key(kwargs['user'])
    print instance.last_login==instance.date_joined,"??????????????????????????????"
    if not instance.last_login==instance.date_joined:
        return HttpResponseRedirect(reverse('dashboard'))

So can anyone please let me know how to redirect a user to /dashboard/ for the normal login, am I doing anything wrong in the above signal code?

Edit

After some modification according to the below answer by pennersr, my AccountAdapter class looks like below

from allauth.account.adapter import DefaultAccountAdapter
# from django.contrib.auth.models import User

class AccountAdapter(DefaultAccountAdapter):

  def get_login_redirect_url(self, request):
    if request.user.last_login == request.user.date_joined:
        return '/registration/success/'
    else:
        return '/dashboard/'

But still, it is redirecting the user to /dashboard/, my logic in determining the first time user is wrong?

Reduction answered 22/11, 2013 at 6:0 Comment(0)
Y
30

In general, you should not try to put such logic in a signal handler. What if there are multiple handlers that want to steer in different directions?

Instead, do this:

# settings.py:
ACCOUNT_ADAPTER = 'project.users.allauth.AccountAdapter'


# project/users/allauth.py:
class AccountAdapter(DefaultAccountAdapter):

  def get_login_redirect_url(self, request):
      return '/some/url/'
Yentai answered 22/11, 2013 at 11:14 Comment(5)
Thanks pennersr, i had edited my anser above, can u please help me out with that ?Reduction
Also can we able to provide user an option to resend the confirmation email ? if not confirmed when he has registered ?Reduction
Have you tried inspecting the values of last_login/date_joined? Resending confirmation emails happens automatically, as soon as the user tries to login with an unverified e-mail. Note that in order to prevent mail bombardments this only kicks in when the login attempts are 3 minutes or so apart.Yentai
Do not name the new file 'project/.../allauth.py' it will then load first in your path and mask the entire allauth library throwing an ImportError.Guthrie
@Yentai would you not mind to help me on issue listed here #24886232Imbibition
K
9

The two datetimes last_login and date_joined will always be different, although it might only be a few milliseconds. This snippet works:

# settings.py:
ACCOUNT_ADAPTER = 'yourapp.adapter.AccountAdapter'

# yourapp/adapter.py:
from allauth.account.adapter import DefaultAccountAdapter
from django.conf import settings
from django.shortcuts import resolve_url
from datetime import datetime, timedelta

class AccountAdapter(DefaultAccountAdapter):

    def get_login_redirect_url(self, request):
        threshold = 90 #seconds

        assert request.user.is_authenticated()
        if (request.user.last_login - request.user.date_joined).seconds < threshold:
            url = '/registration/success'
        else:
            url = settings.LOGIN_REDIRECT_URL
        return resolve_url(url)

One important remark to pennersr answer: AVOID using files named allauth.py as it will confuse Django and lead to import errors.

Kaliski answered 27/2, 2014 at 7:54 Comment(2)
@user2292376 I think the assert is unnecessary here, as this is a login redirect, so the user is supposed to be authenticated at the point this is called. However, +1Overdraw
@DH1TW i believe this solution is not entirely bullet proof... i just realized that if a user attempts a failed login (wrong password) the request.user.last_login still gets updated for some reason, so request.user.last_login != request.user.date_joined and not even the threshold can save it.. do you guys have a solution?Venge
S
3

the answer here is very simple, you do not need any signals or overriding the DefaultAccountAdapter in settings.py just add a signup redirect_url

ACCOUNT_SIGNUP_REDIRECT_URL = "/thanks/"
LOGIN_REDIRECT_URL = "/dashboard/"
Semidome answered 9/12, 2020 at 1:20 Comment(1)
this should really be the accepted answer, I think the others are very old. allauth correctly respects standard django settings, no need for special classes that reimplement framework functionalityDentist
S
0

You can simply define those two other signals using user_logged_in signal as base. A good place to put it is on a signals.py inside a accounts app, in case you have one, or in you core app. Just remember to import signals.py in you __init__.py.

from django.dispatch import receiver, Signal

pre_user_first_login = Signal(providing_args=['request', 'user'])
post_user_first_login = Signal(providing_args=['request', 'user'])


@receiver(user_logged_in)
def handle_user_login(sender, user, request, **kwargs):
    first_login = user.last_login is None
    if first_login:
        pre_user_first_login.send(sender, user=user, request=request)
    print 'user_logged_in'
    if first_login:
        post_user_first_login.send(sender, user=user, request=request)


@receiver(pre_user_first_login)
def handle_pre_user_first_login(sender, user, request, **kwargs):
    print 'pre_user_first_login'


@receiver(post_user_first_login)
def handle_post_user_first_login(sender, user, request, **kwargs):
    print 'post_user_first_login'
Semiotics answered 14/12, 2016 at 13:18 Comment(1)
Note: providing_args may no longer be included as an argument in Signal()Fallow

© 2022 - 2024 — McMap. All rights reserved.