Record Last Access Not Just Last Login

Knowing when a person last logged in is great, except when it isn't. Sometimes you want to know when a user last actually used your app. Since you can stay continually logged in to Django sites we need an alternative way to know when a person was last on your site.

If you are using class based views, and you should, then writing a mixin is a good way to go.

LastAccessMixin

from django.utils import timezone

class LastAccessMixin(object):
    def dispatch(self, request, *args, **kwargs):
        if request.user.is_authenticated():
            request.user.accessdata.last_access = timezone.now()
            request.user.accessdata.save(update_fields=['last_access'])
        return super(LastAccessMixin, self).dispatch(request, *args, **kwargs)

What Does this Code Do?

The first place class based views go is to the disatch method. This "dispatches" the request to the proper place. It determines what type of a request it is be it a GET, POST, HEAD etc. From there it goes to the appropriate method.

def dispatch(self, request, *args, **kwargs):

We are overriding the dispatch method because it is always called, and only once. We also want to use the dispatch method instead of say get because on some urls we might use a post method, then we wouldn't know the page was used.

if request.user.is_authenticated():
    request.user.accessdata.last_access = timezone.now()
    request.user.accessdata.save(update_fields=['last_access'])

In the method, before it routes away, we are wanting to record the user accessed the page. So we are simply updating a model attached to the user model with the current time, then saving it. Nothing too complicated.

return super(LastAccessMixin, self).dispatch(request, *args, **kwargs)

Since we are done recording that the user hit a page we can call the rest of the dispatch so the request continues on properly.

Using LastAccessMixin

The best way to use this mixin is to include it in the declaration of your class based view similar to below:

from django.views.generic import TemplateView
from home.mixins import LastAccessMixin

class IndexView(LastAccessMixin, TemplateView):
    template_name = 'home/index.html'

Now when a user visits the index page, and they are logged in, the time is logged. You can add this mixin to any class based view, and you are set.

Closing Thoughts

This is a quick implementation of this functionality. The mixin can be expanded to be much more robust, and universal. However, this is a good demonstration of the power of mixins, and an easy way to solve what could have been a complex problem.

As a final note since all we want to really know is that users are using the site it is, probably, recommended to choose a few specific views to use this with, and not every single view.

I would be curious if you know of other ways to accomplish this.

comments powered by Disqus