ssc*_*ssc 74 python django signals login
在我的Django应用程序中,我需要在用户登录时开始运行一些定期后台作业,并在用户注销时停止运行它们,所以我正在寻找一种优雅的方式
从我的角度来看,理想的解决方案是
django.contrib.auth.views.login和... views.logoutdjango.contrib.auth.models.User.is_logged_in(),类似于... User.is_active()或... User.is_authenticated()Django 1.1.1没有那个,我不愿修改源代码并添加它(不知道如何做到这一点,无论如何).
作为临时解决方案,我is_logged_in在UserProfile模型中添加了一个布尔字段,该模型默认情况下已清除,在用户第一次访问登录页面(定义方式LOGIN_REDIRECT_URL = '/')时设置,并在后续请求中查询.我将它添加到UserProfile,因此我不必为此目的派生和定制内置用户模型.
我不喜欢这个解决方案.如果用户明确点击了注销按钮,我可以清除该标志,但大多数时候,用户只需离开页面或关闭浏览器; 在这些情况下清除旗帜对我来说似乎并不直接.此外(尽管数据模型的清晰度很明显),is_logged_in不属于UserProfile,而是属于User模型.
谁能想到替代方法?
Pho*_*beB 142
你可以使用这样的信号(我把它放在models.py中)
from django.contrib.auth.signals import user_logged_in
def do_stuff(sender, user, request, **kwargs):
whatever...
user_logged_in.connect(do_stuff)
Run Code Online (Sandbox Code Playgroud)
请参阅django docs:https://docs.djangoproject.com/en/dev/ref/contrib/auth/#module-django.contrib.auth.signals此处http://docs.djangoproject.com/en/dev/专题/信号/
ShZ*_*ShZ 13
一种选择可能是用自己的方式包装Django的登录/注销视图.例如:
from django.contrib.auth.views import login, logout
def my_login(request, *args, **kwargs):
response = login(request, *args, **kwargs)
#fire a signal, or equivalent
return response
def my_logout(request, *args, **kwargs):
#fire a signal, or equivalent
return logout(request, *args, **kwargs)
Run Code Online (Sandbox Code Playgroud)
然后在代码中使用这些视图而不是Django,并且瞧.
关于查询登录状态,如果您有权访问请求对象,则非常简单; 只需检查请求的用户属性,看看他们是注册用户还是匿名用户,以及宾果游戏.引用Django文档:
if request.user.is_authenticated():
# Do something for logged-in users.
else:
# Do something for anonymous users.
Run Code Online (Sandbox Code Playgroud)
如果您无权访问请求对象,那么确定当前用户是否已登录将很困难.
编辑:
不幸的是,你永远无法获得User.is_logged_in()功能 - 这是HTTP协议的限制.但是,如果你做了一些假设,你可能会接近你想要的.
首先,为什么你不能获得这个功能?好吧,你无法区分关闭浏览器的人或者在获取新浏览器之前在页面上花费一些时间的人之间的区别.当有人实际离开网站或关闭浏览器时,无法通过HTTP告知.
所以你有两个不完美的选择:
unload事件来捕获用户离开页面的时间.但是,您必须编写一些谨慎的逻辑,以确保在用户仍在浏览您的网站时不会注销用户.这些解决方案很混乱,并不理想,但不幸的是,它们是你能做的最好的.
除了@PhoebeB回答:你也可以使用@receiver像这样的装饰:
from django.contrib.auth.signals import user_logged_in
from django.dispatch import receiver
@receiver(user_logged_in)
def post_login(sender, user, request, **kwargs):
...do your stuff..`
Run Code Online (Sandbox Code Playgroud)
如果你把它signals.py放在你的app目录中,那么将其添加到app.py:
def ready(self):
import app_name.signals`
Run Code Online (Sandbox Code Playgroud)