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:
- user submit a request
- when view function is called, create an instance.
- 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:
- A is called, create instance 1
- refresh
- A's web socket closed, delete instance
- B is called, create instance 2
And sometimes it works as expected, but other times the sequence turned to:
- A is called, create instance 1
- refresh
- B is called, create instance 2
- 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,
)
# ...