Django: signal when user logs in?

In my Django application, I need to run several periodic background jobs when the user logs in and stops starting them when the user logs out, so I'm looking for an elegant way

  • receive user login / logout notification
  • request user login status

From my point of view, the ideal solution would be

  • the signal sent by each django.contrib.auth.views.login and ... views.logout
  • django.contrib.auth.models.User.is_logged_in() method, similar to ... User.is_active() or ... User.is_authenticated()

In Django 1.1.1, this is not, and I do not want to fix the source code and add it (I donโ€™t know how to do this, anyway).

As a workaround, I added the is_logged_in boolean field to the is_logged_in model, which is cleared by default, set when the user first LOGIN_REDIRECT_URL = '/' landing page (defined by LOGIN_REDIRECT_URL = '/' ) and is requested in subsequent Requests. I added it to UserProfile, so I donโ€™t need to display and configure the built-in user model just for this purpose.

I do not like this solution. If the user explicitly presses the exit button, I can clear the flag, but most of the time, users simply leave the page or close the browser; clearing the flag in these cases does not seem straight to me. In addition (which, rather, is the parity of the model data), is_logged_in does not belong in the UserProfile, but in the User model.

Can anyone think of alternative approaches?

+65
python django login signals user
Jan 02 '09 at 3:19
source share
8 answers

You can use such a signal (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 /

+129
May 24 '11 at 10:58
source share

One option might be to combine the entry / exit views in Django 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) 

Then you use these views in your code, not in Django and voila.

Regarding the request for login status, it is quite simple if you have access to the request object; just check the request user attribute to see if they are a registered user or anonymous user, as well as 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 do not have access to the request object, determining whether the current user will be registered will be difficult.

Edit:

Unfortunately, you can never get the functionality of User.is_logged_in() - this is a limitation of the HTTP protocol. However, if you make a few assumptions, you can get closer to what you want.

First, why can't you get this functionality? Well, you canโ€™t tell the difference between someone who closes the browser, or someone is wasting time on the page before choosing a new one. It is not possible to send an HTTP message when someone really leaves the site or closes the browser.

So, you have two options that are not ideal:

  • Use Javascript unload to catch when the user leaves the page. You should write some careful logic to make sure you are not logged out when the user is still moving your site.
  • Fire the exit signal when the user logs in to be sure. Also, create a cron task that runs quite often to clear expired sessions - when deleting an expired session, make sure that the session user (if it is not anonymous) does not have more active sessions, in which case you start a logout signal.

These decisions are messy and not perfect, but unfortunately, this is the best you can do.

+13
Jan 02 '09 at 3:25
source share

In addition to @PhoebeB's answer: you can also use the @receiver decorator as follows:

 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 in signals.py in your application directory, add it to app.py :

 def ready(self): import app_name.signals` 
+6
Sep 12 '17 at 7:51 on
source share

The only reliable way (which also detects when the user has closed the browser) is to update some last_request field each time the user loads the page.

You may also have a periodic AJAX request that binds the server every x minutes if the user has a page open.

Then you have one background task that receives a list of recent users, creates tasks for them, and clears tasks for users not in this list.

+1
Jan 02 '09 at 12:48
source share

The output of the system, in contrast to the fact that they explicitly press the button (which no one does), means the choice of the amount of downtime, which equates to "logging out". phpMyAdmin uses 15 minutes by default, some banking sites use only 5 minutes.

The easiest way to implement this is to change the cookie lifetime. You can do this for your entire site by specifying settings.SESSION_COOKIE_AGE . Alternatively, you can change it for each user (based on some arbitrary set of criteria) using HttpResponse.setcookie() . You can centralize this code by creating your own version of render_to_response() and setting a lifetime for each answer.

+1
Jan 03 '09 at 17:08
source share

A rough idea - you can use middleware for this. This middleware can process requests and fire alarms when the corresponding URL is requested. It can also process responses and fire signals when a given action is actually being performed.

0
Jan 02 '09 at 12:41
source share

A quick solution for this would be to place the following code in _ _ init _ _.py of your application:

 from django.contrib.auth.signals import user_logged_in from django.dispatch import receiver @receiver(user_logged_in) def on_login(sender, user, request, **kwargs): print('User just logged in....') 
0
Mar 19 '18 at 11:10
source share

You can use the following:

 from django.contrib.auth.signals import user_logged_out, user_logged_in @login_required def user_logout(request): logout(request) user_logged_out() return redirect('post_list') 
-one
Mar 21 '17 at 14:09
source share



All Articles