Django: get last user visit date

Example model:

class User(models.Model):
    last_visit = models.DateTimeField(...)
    ...

Example middleware which will be executed for all logged-in users:

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

Add the new middleware to Your settings.py:

MIDDLEWARE_CLASSES = (
    ...
    'path.to.your.SetLastVisitMiddleware',
    ...
)

Warning: not tested, but doesn't require external packages to be installed and it's only 5 lines of code.

See more in the docs about Middleware and custom user models (since Django 1.5)


Here's a middleware that will keep track of user last activity and count separated by intervals of time. Using the interval creates discrete "sessions" which can be tracked/counted along with the benefit of minimizing writes to the database.

Every time an auth user performs a request, will hit the cache to find their last activity, and then update the cache with a new timestamp. If the activity has had a gap of at least "interval" time, then it will update the database timestamp.

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

Comments:

  1. How you define settings.LAST_ACTIVITY_INTERVAL_SECS determine what constitutes the interval of non-activity considered to be a new login.
  2. This updates a "UserProfile" object which I have 1:1 with my User objects, but you can update any object you please.
  3. Make sure to include this in settings.MIDDLEWARE_CLASSES.
  4. Note this middleware uses process_request not process_response otherwise depending on middleware order, APPEND_SLASH may cause request.user to be unavailable as discussed: Django: WSGIRequest' object has no attribute 'user' on some pages?

Tags:

Django