django - 将 Django 的 GenericForeignKey 与异步石墨烯订阅一起使用
问题描述
我已经实现了 graphql_ws来订阅来自Notification
使用多个GenericForeignKeys
.
我的设置运行良好,除非我尝试从这些异物中查询信息。然后我收到以下错误:
graphql.error.located_error.GraphQLLocatedError: You cannot call this from an async context - use a thread or sync_to_async.
据我所知,这是因为一些数据库查询操作是在异步上下文之外get_notifications
(即在resolve_actor
函数中)完成的。但我真的不清楚如何将操作拉resolve_actor
入异步上下文。
我没有成功尝试使用prefetch_related
(另外我不确定它是否适用于每个 Django 文档的多种内容类型)。
这是代码
模型.py
class Notification(TimeStampedModel):
# ...
actor_content_type = models.ForeignKey(ContentType, related_name='notify_actor', on_delete=models.CASCADE)
actor_object_id = models.CharField(max_length=255)
actor = GenericForeignKey('actor_content_type', 'actor_object_id')
# ...
架构.py
class ActorTypeUnion(graphene.Union):
"""
All possible types for Actors
(The object that performed the activity.)
"""
class Meta:
types = (UserType,) # here's there's only one type, but other fields have multiple
class NotificationType(DjangoObjectType):
actor = graphene.Field(ActorTypeUnion)
def resolve_actor(self, args):
if self.actor is not None:
model_name = self.actor._meta.model_name
app_label = self.actor._meta.app_label
model = ContentType.objects.get(app_label=app_label, model=model_name)
return model.get_object_for_this_type(pk=self.actor_object_id)
return None
# ...
class Meta:
model = Notification
class Subscription(graphene.ObjectType):
unread_notifications = graphene.List(NotificationType)
async def resolve_unread_notifications(self, info, **kwargs):
user = info.context['user']
if user.is_anonymous:
raise Exception('Not logged in!')
@database_sync_to_async
def get_notifications(user):
notifications = Notification.objects.filter(
recipient=user,
read=False,
organization=user.active_organization,
)
return [notifications]
while True:
await asyncio.sleep(1)
yield await get_notifications(user)
查询(一切正常,除非我在 上查询字段actor
)
subscription {
unreadNotifications {
id,
read,
actor {
... on UserType {
__typename,
id
}
}
}
}
完整回溯
Traceback (most recent call last):
File "/Users/benjaminsoukiassian/.pyenv/versions/logbook/lib/python3.8/site-packages/graphql/execution/executor.py", line 452, in resolve_or_error
return executor.execute(resolve_fn, source, info, **args)
File "/Users/benjaminsoukiassian/.pyenv/versions/logbook/lib/python3.8/site-packages/graphql/execution/executors/asyncio.py", line 74, in execute
result = fn(*args, **kwargs)
File "/Users/benjaminsoukiassian/Projects/logbook-back/logbook/notifications/schema.py", line 52, in resolve_actor
model = ContentType.objects.get(app_label=app_label, model=model_name)
File "/Users/benjaminsoukiassian/.pyenv/versions/logbook/lib/python3.8/site-packages/django/db/models/manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/Users/benjaminsoukiassian/.pyenv/versions/logbook/lib/python3.8/site-packages/django/db/models/query.py", line 431, in get
num = len(clone)
File "/Users/benjaminsoukiassian/.pyenv/versions/logbook/lib/python3.8/site-packages/django/db/models/query.py", line 262, in __len__
self._fetch_all()
File "/Users/benjaminsoukiassian/.pyenv/versions/logbook/lib/python3.8/site-packages/django/db/models/query.py", line 1324, in _fetch_all
self._result_cache = list(self._iterable_class(self))
File "/Users/benjaminsoukiassian/.pyenv/versions/logbook/lib/python3.8/site-packages/django/db/models/query.py", line 51, in __iter__
results = compiler.execute_sql(chunked_fetch=self.chunked_fetch, chunk_size=self.chunk_size)
File "/Users/benjaminsoukiassian/.pyenv/versions/logbook/lib/python3.8/site-packages/django/db/models/sql/compiler.py", line 1173, in execute_sql
cursor = self.connection.cursor()
File "/Users/benjaminsoukiassian/.pyenv/versions/logbook/lib/python3.8/site-packages/django/utils/asyncio.py", line 24, in inner
raise SynchronousOnlyOperation(message)
graphql.error.located_error.GraphQLLocatedError: You cannot call this from an async context - use a thread or sync_to_async.
解决方案
推荐阅读
- python - 根据某些条件从 numpy 数组中删除行并连接结果
- python - python中tkinter的输出
- c# - ASP.NET MVC 输入模型绑定,无需再次渲染视图
- typescript - TypeScript:从自定义 d.ts 文件导入
- r - R - 根据另一行的值删除行
- angular - 效果不是调用成功操作并发出多个服务请求
- python - 使用带有 Tkinter 的网格,一个框架中不能容纳多个标签
- node.js - 使用 promise 从 express 中间件返回并从循环中中断返回 404
- python - 猜测 XOR 密钥知道其中的一部分
- excel - 是否可以从具有 3 个参数的特定单元格开始相交列?