class User(models.Model):
last_visit = models.DateTimeField(...)
...
将为所有登录用户执行的示例中间件:
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
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
备注: 1.定义settings.LAST_ACTIVITY_INTERVAL_SECS的方式决定了被视为新登录的非活动时间间隔。 1.这将更新一个"UserProfile"对象,我与我的用户对象是1:1的,但您可以更新任何对象。 1.请确保将其包含在settings.MIDDLEWARE_CLASSES中。 1.请注意,此中间件使用process_request而不是process_response,否则根据中间件订单,APPEND_SLASH可能会导致request.user不可用,如前所述:Django: WSGIRequest' object has no attribute 'user' on some pages?
from django.core.cache import cache
from django.utils import timezone
# other user model import
def last_visit_middleware(get_response):
def middleware(request):
"""
Save the time of last user visit
"""
response = get_response(request)
if request.session.session_key:
key = "recently-seen-{}".format(request.session.session_key)
recently_seen = cache.get(key)
# is_authenticated hits db as it selects user row
# so we will hit it only if user is not recently seen
if not recently_seen and request.user.is_authenticated:
UserAccount.objects.filter(id=request.user.id) \
.update(last_visit=timezone.now())
visit_time = 60 * 30 # 30 minutes
cache.set(key, 1, visit_time)
return response
return middleware
这是我的www.example.com文件,我已将其作为中间件添加到www.example.com文件中 lastvisitmiddleware.py file which I have added in the settings.py file as a middleware
from django.utils.timezone import now
from myapp.models import UserLastVisit
from django.contrib.auth.models import User
class LastVisitMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
if request.user.is_authenticated:
# Update last visit time after request finished processing.
user = User.objects.get(id=request.user.id)
userLastVisit = UserLastVisit.objects.filter(user_id=user)
if userLastVisit:
userLastVisit.update(last_visit=now())
else:
UserLastVisit.objects.create(user_id=user, last_visit=now())
response = self.get_response(request)
return response
# middleware.py
from django.utils.timezone import now
from django.core.cache import cache
class LastActivityMiddleware:
"""Records last activity of a user. This is different of user.last_login
because you can be inactive without been logged out"""
def __init__(self, get_response):
self.get_response = get_response
# One-time configuration and initialization.
def __call__(self, request):
"""Records the timestamp of last activity of a user, every x minutes"""
if request.user.is_authenticated:
last_activity_timeout = 60*10 # 10min expiration
user_last_activity_cache_key = f'{request.user.email}_last_activity'
# in version 1 of cache key, there is an expiration date. This expiration date reprensent
# the cooldown time for the last activity to be updated again, using the second version of the
# key which store the latest activity timestamp value
v2 = cache.get_or_set(user_last_activity_cache_key, now(), timeout=None, version=2)
if not cache.get(user_last_activity_cache_key, version=1):
cache.set(user_last_activity_cache_key, v2, timeout=last_activity_timeout, version=1)
cache.set(user_last_activity_cache_key, now(), timeout=None, version=2)
response = self.get_response(request)
return response
8条答案
按热度按时间lf3rwulv1#
示例型号:
将为所有登录用户执行的示例中间件:
将新中间件添加到您的settings.py:
更多关于Middleware和自定义用户模型的文档(Django 1.5之后)
isr3a4wc2#
这里有一个中间件,它将跟踪用户的最后一次活动,并按时间间隔进行计数。使用时间间隔创建离散的"会话",可以跟踪/计数这些会话,同时还可以最大限度地减少对数据库的写入。
每次身份验证用户执行请求时,将命中高速缓存以查找其最后一个活动,然后使用新的时间戳更新高速缓存。如果活动之间的间隔至少为"interval"时间,则它将更新数据库时间戳。
备注:
1.定义
settings.LAST_ACTIVITY_INTERVAL_SECS
的方式决定了被视为新登录的非活动时间间隔。1.这将更新一个"UserProfile"对象,我与我的用户对象是1:1的,但您可以更新任何对象。
1.请确保将其包含在
settings.MIDDLEWARE_CLASSES
中。1.请注意,此中间件使用
process_request
而不是process_response
,否则根据中间件订单,APPEND_SLASH
可能会导致request.user
不可用,如前所述:Django: WSGIRequest' object has no attribute 'user' on some pages?bihw5rsg3#
考虑到@John Lehmann的解决方案和@Andrew Swihart的建议,我为Django的更新版本(〉2.0)编写了以下代码:
xvw2m8pv4#
@John Lehmann的解决方案非常好,但是它需要使用特定的基于缓存的会话设置,以避免每次请求都写入数据库。
在基于高速缓存的会话中有两个选项,
backends.cache
或backends.cached_db
。第二个选项是直写高速缓存,即对会话数据的每次修改都写入数据库和高速缓存。这提供了重新启动后的持久性。我重新编写了上面的代码,以显式使用该高速缓存函数并避免大量数据库写入。
记录了最后一次到达或最后一次访问的时间。它不记录最后一次退出或“最后一次看到”的时间。
zyfwsgd65#
I would go for django-last-seen
用法:
sxissh066#
与John Lehmann的中间件相同,但使用Andrew Swihart的建议重写为函数,并在Django 2.2上测试:
在官方文档中了解有关编写自己的中间件的更多信息:https://docs.djangoproject.com/en/2.2/topics/http/middleware/#writing-your-own-middleware
qoefvg9y7#
这是我的www.example.com文件,我已将其作为中间件添加到www.example.com文件中 lastvisitmiddleware.py file which I have added in the settings.py file as a middleware
setings.py file
models.py
这个解决方案对我很有效。现在,每次用户访问网站时,UserLastVisit表都会更新为最新的last_visit。其中一个问题是,如果用户在不同的页面之间移动,然后最后一次访问也将被更新。我们可以使用一个时间范围,如24小时或类似的东西,以更新它只有一次在该时间范围内。它结合了本主题中提供的答案中的多种方法
pbossiut8#
我提出了上面的另一个解决方案,使用缓存版本和过期日期来确定一个间隔,在这段时间内我们不想更新“last seen”值: