django.core.exceptions.SynchronousOnlyOperation You cannot call this from an async context - use a thread or sync_to_async

52 views Asked by At

I am using Django channels to implemented web sockets.

I want to get database queries using ORM inside consumers.py.

This is my code:

import json
from channels.generic.websocket import AsyncWebsocketConsumer
from .models import Game
from accounts.models import CustomUser as User
from channels.db import database_sync_to_async


class CameraStreamConsumer(AsyncWebsocketConsumer):

    def __init__(self, *args, **kwargs):
        print("initializing")
        self.counter = 0
        super().__init__(*args, **kwargs)

    async def connect(self):
        await self.accept()
        print("accepted connection")

    async def disconnect(self, close_code):
        pass
        print("disconect connection")
    async def receive(self, text_data=None,):
        print(" iam getting data online")
        data = json.loads(text_data)
        

        if data.get('type') == 'started':

            await self.handle_game_started(data)
        
    
    async def get_game(self, game_id):
        game_obj = await database_sync_to_async(Game.objects.get)(id=game_id)
        return game_obj

    async def get_user(self, user_id):
        user_obj = await database_sync_to_async(User.objects.get)(id=user_id)
        return user_obj
    
    async def handle_game_started(self, data):
        game_id = data.get('game_id')
        user_id = data.get('user_id')
        game_obj = await self.get_game(game_id)
        user_obj = await self.get_user(user_id)
        if game_obj and user_obj:
            game_creator = game_obj.creator
            if game_creator == user_obj:
                print("user is creator")
                await self.send(text_data=json.dumps({'message': f'Game {game_id} Started'}))

I get this error:

django.core.exceptions.SynchronousOnlyOperation: You cannot call this from an async context - use a thread or sync_to_async.

I try also with

from asgiref.sync import sync_to_async

but I still get the same error.

1

There are 1 answers

1
Sarfraz On BEST ANSWER

you can try with this

@database_sync_to_async
def get_user(self, user_id):
    return User.objects.filter(id=user_id).last()

async def handle_game_started(self, data):
    user_id = data.get('user_id')
    user_obj = await self.get_user(user_id)
    print(user_obj, "userobjects")