Обновление поля is_online на true при входе пользователя в систему
Построение логики, которая при входе пользователя в систему будет менять булево поле в моей модели Profile на true и затем превращать его в false, когда пользователь выходит из системы. Проблема в том, что у меня есть точка api_end, где я могу видеть список всех пользователей и информацию, связанную с ними.
Если я вхожу в систему как два разных пользователя (используя разные браузеры), когда я регистрирую их информацию на консоли, оба пользователя отображаются как онлайн:
email: "user@gmail.com"
...
is_online: true
...
Однако, когда я проверяю точку api_end, показывающую мне список всех пользователей, только 1 пользователь оказывается онлайн (последний пользователь, под которым я вошел в систему).
Это представление связано с api_end точкой для просмотра всех пользователей:
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all().order_by('-date_joined')
serializer_class = RegisterSerializer
@action(detail=True, methods=['POST'])
def set_password(self, request, pk=None):
user = self.get_object()
serializer = PasswordSerializer(data=request.data)
if serializer.is_valid():
user.set_password(serializer.validated_data['new_password'])
user.save()
return Response({'status': 'password set'})
else:
return Response(serializer.errors,
status=status.HTTP_400_BAD_REQUEST)
Это мой RegisterSerializer:
class RegisterSerializer(serializers.ModelSerializer):
profile = ProfileSerializer()
class Meta:
model = User
fields = ['username', 'email', 'password', 'first_name', 'last_name', 'profile']
extra_kwargs = {
'password': {'write_only': True},
}
def validate_password(self, value):
validate_password(value)
return value
def create(self,validated_data):
profile_data = validated_data.pop('profile')
user = User.objects.create(**validated_data)
Profile.objects.create(**profile_data, user=user)
return user
Это моя модель профиля:
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
city = models.CharField(max_length=50, blank=True)
country = models.CharField(max_length=50, blank=True)
bio = models.CharField(max_length=500, blank=True)
profile_pic = models.ImageField(upload_to='profile/%Y/%m/%d', default='media/placeholder.png', blank=False,
null=False)
is_online = models.BooleanField(default=False)
currently_active = models.BooleanField(default=False)
is_in_session = models.BooleanField(default=False)
@receiver(user_logged_in)
def got_online(sender, user, request, **kwargs):
user.profile.is_online = True
user.profile.save()
@receiver(user_logged_out)
def got_offline(sender, user, request, **kwargs):
user.profile.is_online = False
user.profile.save()
@receiver(post_save, sender=user)
def update_profile_signal(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
instance.profile.save()
Это функция, которая срабатывает, когда пользователь входит в систему - здесь я устанавливаю поле user.profile.is_online
в true, когда пользователь входит в систему. Я предполагаю, что проблема возникает именно здесь.
class CustomTokenObtainPairSerializer(TokenObtainPairSerializer):
def validate(self, attrs):
authenticate_kwargs = {
self.username_field: attrs[self.username_field],
"password": attrs["password"],
}
try:
authenticate_kwargs["request"] = self.context["request"]
except KeyError:
pass
user = authenticate(**authenticate_kwargs)
if not user:
return {
'user': 'Username or password is incorrect',
}
token = RefreshToken.for_user(user)
# customizing token payload
token['username'] = user.username
token['first_name'] = user.first_name
token['last_name'] = user.last_name
token['country'] = user.profile.country
token['city'] = user.profile.city
token['bio'] = user.profile.bio
token['photo'] = json.dumps(str(user.profile.profile_pic))
user_logged_in.send(sender=user.__class__, request=self.context['request'], user=user)
if not api_settings.USER_AUTHENTICATION_RULE(user):
raise exceptions.AuthenticationFailed(
self.error_messages["no_active_account"],
"no_active_account",
)
return {
'refresh': str(token),
'access': str(token.access_token),
}