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?

4 Answers 4

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/'
Sign up to request clarification or add additional context in comments.

5 Comments

Thanks pennersr, i had edited my anser above, can u please help me out with that ?
Also can we able to provide user an option to resend the confirmation email ? if not confirmed when he has registered ?
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.
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.
@pennersr would you not mind to help me on issue listed here stackoverflow.com/questions/24885732/…
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.

2 Comments

@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, +1
@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?
8

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/"

1 Comment

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 functionality
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'

1 Comment

Note: providing_args may no longer be included as an argument in Signal()

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.