Django Channels disconnect called before view after refresh

I met a bug, totally exploded my mind. I don't know how it is possible, I would like to share, and please, if you can offer knowledge and perhaps a solution with me.

here's a basic structure of my code:

  1. user submit a request
  2. when view function is called, create an instance.
  3. when web socket disconnect, delete the instance.

the issue is: when I refresh the page on my location machine, sometimes last web socket is closed after view function is called

I don't know why this happens, let's call the page A and after refresh, new page B, shouldn't it be:

  1. A is called, create instance 1
  2. refresh
  3. A's web socket closed, delete instance
  4. B is called, create instance 2

And sometimes it works as expected, but other times the sequence turned to:

  1. A is called, create instance 1
  2. refresh
  3. B is called, create instance 2
  4. A's web socket closed, delete instance

and it breaks my code due to filter applied in deletion which the instance I needed after refresh is gone!

I don't know if I should do anything, because I reckon there is a big chance that this only happens on local machine.


some extracted code

view

@login_required
def chatFriendsView(request):
    # ...
    toread = Toread(
        sender=sender,
        receiver=request.user, 
    )
    toread.save()
    return render(request, 'chat/chat_friends.html')

model

class Toread(models.Model):
    sender = models.ForeignKey(User, on_delete=models.CASCADE, related_name='sendToread')
    receiver = models.ForeignKey(User, on_delete=models.CASCADE, related_name='receiveToread')
    # ...

    def __str__(self):
        return str(self.receiver)

ws

class ChatConsumer(AsyncJsonWebsocketConsumer):
    @staticmethod
    @database_sync_to_async
    def dismissToread(sender_pk, receiver_pk):
        for tr in Toread.objects.filter(
            sender=User.objects.get(pk=sender_pk), 
            receiver=User.objects.get(pk=receiver_pk), 
        ):
            tr.delete()

    async def disconnect(self, close_code):
        await ChatConsumer.dismissToread(
            sender_pk=int(self.scope['user'].pk),
            receiver_pk=int(self.room_name), 
        )
        await self.channel_layer.group_discard(
            self.room_group_name, 
            self.channel_name, 
        )

    # ...
    

Back to Top