使用django-allauth登录信号将用户重定向到另一个URL

27
我正在使用Django-allauth来处理登录/注册相关的事宜,因此当用户第一次在我的网站上注册时,我通过在settings.py文件中定义以下设置将其重定向到/thanks/页面: < p > LOGIN_REDIRECT_URL = '/thanks/'

但是当用户尝试再次登录(如果已经注册),我应该将他重定向到'/dashboard/' URL。
所以我尝试像下面这样通过Django-allauth signals进行修改,但根本不起作用。
@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'))

有谁能告诉我如何在正常登录时将用户重定向到/dashboard/,我在上面的信号代码中做错了什么吗?

编辑

根据pennersr的回答进行一些修改后,我的AccountAdapter类如下所示:

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

但是,它仍然将用户重定向到/dashboard/,我的逻辑判断首次用户的方法有误吗?

4个回答

30

一般来说,您不应该尝试将这样的逻辑放在信号处理程序中。如果有多个处理程序希望朝不同方向引导该逻辑会怎样呢?

相反,请按照以下方式操作:

# 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/'

谢谢pennersr,我已经编辑了我的答案,你能帮我看一下吗? - Shiva Krishna Bavandla
我们能否为用户提供重新发送确认电子邮件的选项?如果用户在注册时未确认,可以吗? - Shiva Krishna Bavandla
你尝试过检查last_login/date_joined的值吗?重新发送确认电子邮件是自动进行的,只要用户尝试使用未经验证的电子邮件登录即可。请注意,为了防止邮件轰炸,这仅在登录尝试间隔约3分钟时才会启动。 - pennersr
请勿将新文件命名为“project/.../allauth.py”,否则它将首先加载到您的路径中,并掩盖整个allauth库,从而引发ImportError。 - eezis
@pennersr,您是否可以帮我解决这个问题?问题详情请见此链接:http://stackoverflow.com/questions/24885732/allauth-redirect-to-custom-form-page-before-successful-signup - Lionel

9

两个日期时间变量last_logindate_joined总是不同的,尽管可能只相差几毫秒。以下代码片段可以正常工作:

# 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)

对pennersr回答的一个重要说明避免使用文件名为allauth.py,因为这会让Django感到困惑并导致导入错误


谢谢,那很有帮助。 - Shiva Krishna Bavandla
@user2292376 我认为这里的assert是不必要的,因为这是一个登录重定向,所以在调用此函数时用户应该已经通过身份验证。不过,点赞加一。 - Caumons
@DH1TW 我认为这个解决方案并不完全可靠...我刚刚意识到,如果用户尝试登录失败(密码错误),请求.用户.最后登录仍然会因某种原因而更新,所以请求.用户.最后登录!=请求.用户.日期加入,甚至阈值也无法保存它...你们有解决方案吗? - psychok7

2
这里的答案非常简单,您不需要任何信号或重写DefaultAccountAdaptersettings.py中,只需添加一个注册重定向网址即可。
ACCOUNT_SIGNUP_REDIRECT_URL = "/thanks/"
LOGIN_REDIRECT_URL = "/dashboard/"

0
你可以使用user_logged_in信号作为基础,简单地定义这两个其他信号。一个好的放置位置是在accounts应用程序中的signals.py文件中,如果你有的话,或者在你的core应用程序中。只需记得在你的__init__.py文件中导入signals.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'

注意:providing_args可能不再作为Signal()的参数包含。 - Rob

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接