What i am trying to do is to nest a DRF model serializer into another model serialiser's field like so
class username_serial(ModelSerializer):
class Meta:
model = User
fields = ['username','email']
class game_serial(ModelSerializer):
user_01 = username_serial()
class Meta:
model = game
fields = ['id','user_01','user_02','is_private','is_accepted']
Error :
Exception inside application: You cannot call this from an async context - use a thread or sync_to_async. Traceback (most recent call last): File "C:\Users\baza\Desktop\production\venv\lib\site-packages\django\db\models\fields\related_descriptors.py", line 173, in get rel_obj = self.field.get_cached_value(instance) File "C:\Users\baza\Desktop\production\venv\lib\site-packages\django\db\models\fields\mixins.py", line 15, in get_cached_value return instance._state.fields_cache[cache_name] KeyError: 'user_01'
This works normally without Django Chennels because channels is async and i can't use sync code with, works fine by using:
os.environ["DJANGO_ALLOW_ASYNC_UNSAFE"] = "true"
In the settings file but it's not a safe approach when it comes to production. i tried using channel's database_sync_to_async as a decorator and as well as a function with a SerializerMethodField like so:
class game_serial(ModelSerializer):
user_01 = SerializerMethodField(read_only=True)
@database_sync_to_async
def get_user_01(self, obj):
username = obj.user_01.username
return str(username)
class Meta:
model = game
fields = ['id','user_01','user_02','is_private','is_accepted']
but i get back:
[OrderedDict([('id', 23), ('user_01', <coroutine object SyncToAsync.__call__ at 0x0000000005DF6678>), ('user_02', None), ('is_private', False), ('is_accepted', False)]), OrderedDict([('id', 24), ('user_01', <coroutine object SyncToAsync.__call__ at 0
x0000000005DF6D58>), ('user_02', None), ('is_private', False), ('is_accepted', False)])]
with an
Exception inside application: Object of type 'coroutine' is not JSON serializable
so i guess that JSON couldn't serialize those "coroutine" objects and normally i should or "want" to get the actual values of them instead.
How can i do the task? any workaround or other methods are welcomed, thank you in advance.
in consumers.py ..
games = await database_sync_to_async(self.get_games)()
serialized_games = game_serial(games, many=True)
await self.send({
"type": "websocket.send",
'text': json.dumps(serialized_games.data)
})
def get_games(self):
return list(game.objects.all())