Sometimes we want to detect information about user’s first login, e.g. to show account detail or edit form.
First thought would be to look at last_login field in User model, but… it is filled with date after user signed up and doesn’t logged in yet.
So, can we assume that User.last_login and User.date_joined fields have equal value after registration? I think it is too risky - dates might be equal but it is not guaranteed.
In this case we must extend our user profile model (more on this topic: http://docs.djangoproject.com/en/dev/topics/auth/#storing-additional-information-about-users). This is not the cleanest method but the simplest one.
Let’s add new field to out UserProfile model:
class UserProfile(models.Model):
"""Additional user fields"""
user = models.ForeignKey(User, unique=True)
(...)
is_first_login = models.BooleanField(default=True,
verbose_name=_(u"Is first login?"))
Okay, now we need to detect user login and check if it is his first attempt. We will create custom middleware to do the check.
Middleware should be located in settings.py’s MIDDLEWARE_CLASSES after ‘django.contrib.auth.middleware.AuthenticationMiddleware’:
MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'users.middleware.FirstLoginMiddleware',
(...)
)
This is FirstLoginMiddleware (e.g. users.middleware.FirstLoginMiddleware):
# -*- coding: utf-8 -*-
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect
class FirstLoginMiddleware(object):
def process_request(self, request):
if request.user.is_authenticated() and "dont_check_first_login" \
not in request.session:
request.session["dont_check_first_login"] = True
profile = request.user.get_profile()
if profile.is_first_login:
profile.is_first_login = False
profile.save()
return HttpResponseRedirect(reverse('users:account_edit'))
As you can see, we used session variable named “dont_check_first_login” (long name, isn’t it?).
It is used to determine that user has already logged in so we don’t query database in each request. Consider caching user profile in real life app - this code is example how to catch first login.

