I\'m writing a User system that cannot login at the same time. If the account in login state in somewhere, and someone login the same account in other position. The latter o
I think you make things very complicated, by storing data in UserProfiles, etc. and then have signals, you introduce a lot of levels, and at each level, things can go wrong.
We basically need two things here: a table that maps Users to their corresponding settings. We can implement this with a UserSession model:
# models.py
from django.conf import settings
from django.db import models
from django.contrib.sessions.models import Session
class UserSession(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
session = models.OneToOneField(Session, on_delete=models.CASCADE)
So the UserSession object makes a link between User and Sessions. Now we can implement a login hook: a signal that is triggered in case a user logs in. In that case we perform two things:
Sessions (and corresponding UserSessions) of the User that are active; andSession and corresponding UserSession that we can remove later. Like:from django.contrib.auth import user_logged_in
from django.dispatch.dispatcher import receiver
@receiver(user_logged_in)
def remove_other_sessions(sender, user, request, **kwargs):
# remove other sessions
Session.objects.filter(usersession__user=user).delete()
# save current session
request.session.save()
# create a link from the user to the current session (for later removal)
UserSession.objects.get_or_create(
user=user,
session=Session.objects.get(pk=request.session.session_key)
)
Since you want the user to have only one session at a time, you can call logout before you call login
...
if user is not None and user.is_active:
auth.logout(request)
auth.login(request, user)
Logout documentation: https://docs.djangoproject.com/en/3.0/topics/auth/default/#django.contrib.auth.logout