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

Posted

技术标签:

【中文标题】使用 django-allauth 登录信号将用户重定向到另一个 url【英文标题】:Redirect User to another url with django-allauth log in signal 【发布时间】:2013-12-06 22:20:58 【问题描述】:

我将 Django-allauth 用于我的登录/注册相关内容,因此当用户(第一次)注册到我的网站时,我通过在 settings.py 文件中定义以下设置将他重定向到 /thanks/ 页面

LOGIN_REDIRECT_URL = '/谢谢/'

但是当用户下次尝试登录时(如果已经注册)我应该将他重定向到'/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/,我确定第一次用户的逻辑是错误的?

【问题讨论】:

【参考方案1】:

一般来说,您不应尝试将此类逻辑放入信号处理程序中。如果有多个处理程序想要转向不同的方向怎么办?

相反,这样做:

# 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,我在上面编辑了我的分析器,你能帮我解决这个问题吗? 我们也可以为用户提供重新发送确认电子邮件的选项吗?如果他注册时没有确认? 您是否尝试过检查 last_login/date_joined 的值?一旦用户尝试使用未经验证的电子邮件登录,就会自动重新发送确认电子邮件。请注意,为了防止邮件轰炸,只有在登录尝试相隔 3 分钟左右时才会启动。 不要将新文件命名为 'project/.../allauth.py',然后它将首先加载到您的路径中并屏蔽整个 allauth 库并引发 ImportError。 @pennersr 你能帮我解决这里列出的问题吗***.com/questions/24885732/…【参考方案2】:

last_logindate_joined 两个日期时间总是不同的,尽管可能只有几毫秒。这个 sn-p 有效:

# 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 并导致 import错误

【讨论】:

谢谢,很有帮助 @user2292376 我认为assert 在这里是不必要的,因为这是一个登录重定向,所以用户应该在调用时进行身份验证。但是,+1 @DH1TW 我相信这个解决方案并不完全是防弹的......我刚刚意识到,如果用户尝试登录失败(密码错误),request.user.last_login 仍然会因某种原因而更新,所以 request.user.last_login != request.user.date_joined 甚至阈值都无法保存..你们有解决方案吗?【参考方案3】:

您可以使用 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()【参考方案4】:

这里的答案很简单,你不需要任何信号或覆盖DefaultAccountAdaptersettings.py 中添加一个注册redirect_url

ACCOUNT_SIGNUP_REDIRECT_URL = "/thanks/"
LOGIN_REDIRECT_URL = "/dashboard/"

【讨论】:

以上是关于使用 django-allauth 登录信号将用户重定向到另一个 url的主要内容,如果未能解决你的问题,请参考以下文章

django-allauth:将多个社交帐户链接到单个用户

使用 django-allauth 启用 oauth 登录,但使用自定义提供程序

使用来自 django-allauth 的访问令牌登录 Spotify iOS SDK

如何使用 django-allauth 访问用户名和配置文件

如何使用 django-allauth 访问用户名和配置文件

django-allauth 检索头像头像