使用 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_login
和 date_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】:
这里的答案很简单,你不需要任何信号或覆盖DefaultAccountAdapter
在settings.py
中添加一个注册redirect_url
ACCOUNT_SIGNUP_REDIRECT_URL = "/thanks/"
LOGIN_REDIRECT_URL = "/dashboard/"
【讨论】:
以上是关于使用 django-allauth 登录信号将用户重定向到另一个 url的主要内容,如果未能解决你的问题,请参考以下文章
使用 django-allauth 启用 oauth 登录,但使用自定义提供程序
使用来自 django-allauth 的访问令牌登录 Spotify iOS SDK
如何使用 django-allauth 访问用户名和配置文件