Django:获取最后一次用户访问日期

use*_*706 24 django

在Django中,我们可以通过使用获得用户上次登录的时间Auth.User.last_login.仅当用户使用其用户名/密码登录时才会更新.假设用户已经登录并且身份验证信息保存在cookie中,因此无需登录即可访问该站点.我们如何获取用户以前访问过该站点的日期?这对于诸如获取自上次访问以来的新记录数量之类的查询非常有用.

Han*_*ody 28

示例型号:

class User(models.Model):
    last_visit = models.DateTimeField(...)
    ...
Run Code Online (Sandbox Code Playgroud)

将为所有登录用户执行的示例中间件:

from django.utils.timezone import now

class SetLastVisitMiddleware(object):
    def process_response(self, request, response):
        if request.user.is_authenticated():
            # Update last visit time after request finished processing.
            User.objects.filter(pk=request.user.pk).update(last_visit=now())
        return response
Run Code Online (Sandbox Code Playgroud)

将新中间件添加到您的settings.py:

MIDDLEWARE_CLASSES = (
    ...
    'path.to.your.SetLastVisitMiddleware',
    ...
)
Run Code Online (Sandbox Code Playgroud)

警告:未经测试,但不需要安装外部软件包,只需5行代码.

有关中间件自定义用户模型的文档中的更多信息(自Django 1.5起)


Joh*_*ann 15

这是一个中间件,它将跟踪用户上次活动和按时间间隔分隔的计数.使用间隔创建离散的"会话",可以跟踪/计算这些会话以及最小化对数据库的写入的好处.

每次auth用户执行请求时,都会点击缓存以查找其上一个活动,然后使用新的时间戳更新缓存.如果活动的间隔至少为"间隔"时间,则它将更新数据库时间戳.

from datetime import timedelta as td
from django.utils import timezone
from django.conf import settings
from django.db.models.expressions import F    
from <user profile path> import UserProfile  

class LastUserActivityMiddleware(object):
    KEY = "last-activity"

    def process_request(self, request):
        if request.user.is_authenticated():
            last_activity = request.session.get(self.KEY)

            # If key is old enough, update database.
            too_old_time = timezone.now() - td(seconds=settings.LAST_ACTIVITY_INTERVAL_SECS)
            if not last_activity or last_activity < too_old_time:
                UserProfile.objects.filter(user=request.user.pk).update(
                        last_login=timezone.now(),
                        login_count=F('login_count') + 1)

            request.session[self.KEY] = timezone.now()

        return None
Run Code Online (Sandbox Code Playgroud)

评论:

  1. 您如何定义settings.LAST_ACTIVITY_INTERVAL_SECS确定什么构成被视为新登录的非活动的间隔.
  2. 这会更新一个"UserProfile"对象,我的用户对象只有1:1,但您可以更新任何对象.
  3. 一定要包括这个settings.MIDDLEWARE_CLASSES.
  4. 注意这个中间件使用process_requestprocess_response依赖于中间件顺序,APPEND_SLASH可能导致request.user不可用,如下所述:Django:WSGIRequest'对象在某些页面上没有属性'user'?

  • 我必须添加`from dateutil.parser import parse`并将`if not last_activity或last_activity <too_old_time:`替换为`if not last_activity或parse(last_activity)<too_old_time:`.........和.. ..........`request.session [self.KEY] = timezone.now()`with`request.session [self.KEY] = timezone.now().isoformat()` (5认同)
  • 忘了提到原因:Django会话显然需要JSON可序列化数据,其日期时间如timezone.now()不是,所以我不得不使用datetime.isoformat()将其存储为字符串,并将其解析回日期时间. (5认同)