Django: signal when user logs in?
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
- get notified of a user login/logout
- query user login status
From my perspective, the ideal solution would be
- a signal sent by each
django.contrib.auth.views.login
and... views.logout
- a method
django.contrib.auth.models.User.is_logged_in()
, analogous to... User.is_active()
or... User.is_authenticated()
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 ?
Solution 1:
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)
See django docs: https://docs.djangoproject.com/en/dev/ref/contrib/auth/#module-django.contrib.auth.signals and here http://docs.djangoproject.com/en/dev/topics/signals/
Solution 2:
In addition to @PhoebeB answer:
you can also use @receiver
decorator like this:
from django.contrib.auth.signals import user_logged_in
from django.dispatch import receiver
@receiver(user_logged_in)
def post_login(sender, user, request, **kwargs):
...do your stuff..
And if you put it into signals.py
in your app dir, then add this to apps.py
:
class AppNameConfig(AppConfig):
...
def ready(self):
import app_name.signals