You can avoid errors that can occur as a result of updating data (in the database) that are in the self.scope that the code may depend on as these data won't be updated #1742
-
I'm building an app where users can play online together , after each game ends I should save the win and lose counter for each player . I'm writing sync code and I don't have any idea why is this happening Note : i'm using this weird competitor thing to prevent any one from sending that he won to the socket , so only the user can confirm the competitors has won my consumers.py def receive(self, text_data):
player = Room.objects.get(channel_name=self.room_group_name).presence_set.filter(channel_name=self.channel_name)
if not player.exists():
self.send(json.dumps({
'type':'error',
'code':'408',
'error':'Time out! You have to play in 15 seconds'
}))
self.close()
return
text_data = json.loads(text_data)
if text_data['type'] == 'completed':
competitor:CustomUser = Room.objects.get(channel_name=self.room_group_name).presence_set.filter(~Q(channel_name=self.channel_name)).first().user
user:CustomUser = self.scope['user']
db_logger.info(f'Game ended between me {user} and {competitor}\nuser scores: {user.won_games}, {user.lost_games}, {user.draw_games}\ncompetitor scores: {competitor.won_games}, {competitor.lost_games}, {competitor.draw_games}')
if competitor:
competitor.win()
if user.is_authenticated:
user.lose()
db_logger.info(f'Game saved between me {user} and {competitor}\nuser scores: {user.won_games}, {user.lost_games}, {user.draw_games}\ncompetitor scores: {competitor.won_games}, {competitor.lost_games}, {competitor.draw_games}')
return
elif text_data['type'] == 'draw':
competitor:CustomUser = Room.objects.get(channel_name=self.room_group_name).presence_set.filter(~Q(channel_name=self.channel_name)).first().user
if competitor:
competitor.draw_games += 1
competitor.save()
user = self.scope['user']
if user.is_authenticated:
user.draw_games += 1
user.save()
return
# some code to handle some other types models.py class CustomUser(AbstractUser):
won_games = models.IntegerField(default=0)
lost_games = models.IntegerField(default=0)
draw_games = models.IntegerField(default=0)
def win(self):
self.won_games += 1
self.save()
def lose(self):
self.lost_games += 1
self.save()
def draw(self):
self.draw_games += 1
self.save() |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 2 replies
-
so the problem was in this line user:CustomUser = self.scope['user'] which uses the scope of the instance of the consumer , this scope has just a copy of information about the user at the initiation point which means updating any info about the user after the connection wouldn't affect the user in the scope which mean saving this user object will override the new updated data which exactly what happened and could be fixed by re fetching the user object from the database so the code should be user:CustomUser = self.scope['user']
user = CustomUser.objects.get(pk=user.pk) and every thing is fine now . |
Beta Was this translation helpful? Give feedback.
so the problem was in this line
which uses the scope of the instance of the consumer , this scope has just a copy of information about the user at the initiation point which means updating any info about the user after the connection wouldn't affect the user in the scope which mean saving this user object will override the new updated data which exactly what happened and could be fixed by re fetching the user object from the database so the code should be
and every thing is fine now .
I haven't read the source code , but I suggest that you can change the self.scope attribute…