In my Django app, I need to start running a few periodic background jobs when a user logs in and stop running them when the user logs out, so I am looking for an elegant way to
From my perspective, the ideal solution would be
django.contrib.auth.models.User.is_logged_in(), analogous to
Django 1.1.1 does not have that and I am reluctant to patch the source and add it (not sure how to do that, anyway).
As a temporary solution, I have added an
is_logged_in boolean field to the UserProfile model which is cleared by default, is set the first time the user hits the landing page (defined by
LOGIN_REDIRECT_URL = '/') and is queried in subsequent requests. I added it to UserProfile, so I don't have to derive from and customize the builtin User model for that purpose only.
I don't like this solution. If the user explicitely clicks the logout button, I can clear the flag, but most of the time, users just leave the page or close the browser; clearing the flag in these cases does not seem straight forward to me. Besides (that's rather data model clarity nitpicking, though),
is_logged_in does not belong in the UserProfile, but in the User model.
Can anyone think of alternate approaches ?
You can use a signal like this (I put mine in models.py)
from django.contrib.auth.signals import user_logged_in def do_stuff(sender, user, request, **kwargs): whatever... user_logged_in.connect(do_stuff)
One option might be to wrap Django's login/logout views with your own. For example:
from django.contrib.auth.views import login, logout def my_login(request, *args, **kwargs): response = login(request, *args, **kwargs) #fire a signal, or equivalent return response def my_logout(request, *args, **kwargs): #fire a signal, or equivalent return logout(request, *args, **kwargs)
You then use these views in your code rather than Django's, and voila.
With regards to querying login status, it's pretty simple if you have access to the request object; simply check request's user attribute to see if they're a registered user or the anonymous user, and bingo. To quote the Django documentation:
if request.user.is_authenticated(): # Do something for logged-in users. else: # Do something for anonymous users.
If you don't have access to the request object, then determining if the current user is logged in is going to be difficult.
Unfortunately, you'll never be able to get
User.is_logged_in() functionality - it's a limitation of the HTTP protocol. If you make a few assumptions, however, you might be able to get close to what you want.
First, why can't you get that functionality? Well, you can't tell the difference between someone closing the browser, or someone spending a while on a page before fetching a new one. There's no way to tell over HTTP when someone actually leaves the site or closes the browser.
So you have two options here that aren't perfect:
unloadevent to catch when a user is leaving a page. You'd have to write some careful logic to make sure you aren't logging out a user when they're still navigating your site, however.
These solutions are messy and not ideal, but they're the best you can do, unfortunately.