graphql-python / graphql-python/graphql-ws

Deep nested objects in django won't work due to async

オープン
#84 コメント 6 件 リアクション 3 件 担当者 0 名 GitHub で見る
主要言語
Python
スター
270
フォーク
85
PR マージ指標
30日以内にマージされた PR はありません

説明

* GraphQL AioWS version: (not using AioWS, only django-channels)
* Python version: 3.8.2
* Operating System: MacOSX

### Description

I am trying to get clients to subscribe to my graphql with a nested object in django. The request looks like this:
```
subscription {
taskUpdated(id:"04a5e92bc9084ad981481ab4314a1d33", updateInterval: 3) {
id
token
result {
id,
profiles {
id
}
}
}
}
```
Tasks contain one result which contain multiple profiles.

### What I Did

In my subscription class I used the sync_to_async method which works if used for the first level:
```python
class Subscription(graphene.ObjectType):
task_updated = graphene.Field(
TaskType, id=graphene.String(), update_interval=graphene.Int()
)

async def resolve_task_updated(root, info, id, update_interval):
print("TRYING TO RESOLVE")
while True:
print("While true")
task = await sync_to_async(Task.objects.get, thread_sensitive=True)(
pk=id
)
yield task
await asyncio.sleep(update_interval)
```

Using the query only targeting task.id everything works perfectly. Once I try to target task.result (which is a new object). I receive the error:

```
You cannot call this from an async context - use a thread or sync_to_async.
```

I managed to get a workaround by updating the TaskType and updating the resolver for the result like so:

```python
class TaskType(DjangoObjectType):
class Meta:
model = TaskModel
fields = "__all__"

result = graphene.Field(TaskResultType)

async def resolve_result(self, info):
return await sync_to_async(
TaskResult.objects.get, thread_sensitive=True
)(task=self.id)
```

That way I could get to the next level (task -> result). When I try to subscribe to task -> result -> profiles there is no way to receive the data anymore. The same error from above is thrown. Even if I update the ResultType accordingly to fetch all profiles async:

```python
class TaskResultType(DjangoObjectType):
class Meta:
model = TaskResult
fields = "__all__"

profiles = graphene.List(ProfileType)

async def resolve_profiles(self, info):
return await sync_to_async(
Profile.objects.filter, thread_sensitive=True
)(task_result=self.id)
```

I thought dynamic querying of objects and subscribing to nested objects would be an out of the box functionality but it is really difficult. I can't be the only person using this repo to actually receive ORM data?

コントリビューションガイド

コントリビューションガイドを開く

評価

この issue はまだ評価されていません。

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。