在我维护的Django应用程序中,用户登录并互相交换消息,论坛风格。在任何给定的时间点,我通过检查在最后5分钟内登录session
对象的人来显示谁在线。为了实现这一点,我使用Django插件user_sessions,允许像常规ORM一样操作会话。
我完成此任务的代码是:
class WhoseOnlineView(ListView):
model = Session
template_name = "whose_online.html"
def get_queryset(self):
unique_user_sessions = Session.objects.filter(last_activity__gte=(timezone.now()-timedelta(minutes=5))).only('user').distinct('user')
users = [session.user for session in unique_user_sessions]
users = [user for user in users if user is not None] #sanitizing None values
return users
网站的用户(和功能)已大幅增长,而且根据newrelic,此特定视图在我的所有视图中消耗的时间最多。
我认为我应该将整个任务移动到异步完成。我在我的生产服务器上使用cevis(使用redis作为消息代理)并在supervisord下运行。
这可能是一项定期任务,每60秒执行一次。但似乎要实现这一点,我需要在数据库(或缓存)中保存结果,以便用户可以看到保存的结果,直到下次其在线列表处理完毕。
有人可以给我一个关于如何实现这个目标的说明性例子吗?我努力解决的主要问题是如何在下一个周期性任务开始之前保存(或缓存)随后显示给用户的结果。
答案 0 :(得分:0)
您可以执行以下操作:
首先,编写芹菜任务以找出登录用户,例如
# fooapp.tasks
@shared_task
def whoseonline():
unique_user_sessions = Session.objects.filter(last_activity__gte=(timezone.now()-timedelta(minutes=5))).only('user').distinct('user')
users = [session.user for session in unique_user_sessions users = [user for user in users if user is not None] #sanitizing None values
# save the users to the cache
cache.set('online_users', users, 70) # expiring in 70 seconds
并设置任务以便运行一定的时间,例如60秒,加上这个:
# settings.py
CELERYBEAT_SCHEDULE = {
'whoseonline': {
'task': 'fooapp.tasks.whoseonline',
'schedule': timedelta(seconds=60), # execute every 60 seconds
'args': (),
},
}
到您的设置。然后,在您的视图中,您只需要执行
class WhoseOnlineView(ListView):
model = Session
template_name = "whose_online.html"
def get_queryset(self):
# take the values from the cache
return cache.get('online_users')
您还应该记住,缓存时间到期(样本中的70秒)应该大于您将用于芹菜任务的预定时间(样本中为60秒),以便视图始终具有某些内容秀。