首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >异步函数(通道使用者) Django中的数据库抓取模型

异步函数(通道使用者) Django中的数据库抓取模型
EN

Stack Overflow用户
提问于 2020-11-30 04:39:14
回答 1查看 967关注 0票数 1

摘要

你好,目前我正在开发一个应用程序,该应用程序通过django-通道在实时时将数据发送到前端。我已经能够为所有在打开页面时创建的模型这样做了,但是我还没有能够抓取以前的模型,因为页面还没有打开。

代码

下面是我第一次尝试让这个系统正常工作,这将在使用者连接方法被触发时调用,并且在连接被接受之后,我将运行这个for循环。

代码语言:javascript
复制
for app in Application.objects.all():
    app_json = ApplicationSerializer(app).data
    await self.send_json({'action': 'create', 'data': app_json})

在运行这段代码时,我将得到django.core.exceptions.SynchronousOnlyOperation: You cannot call this from an async context - use a thread or sync_to_async.的错误消息

这是有意义的,因为使用者连接方法是异步的,所以按照消息的建议,我继续使用sync_to_async

代码语言:javascript
复制
for app in sync_to_async(Application.objects.all)():
    app_json = ApplicationSerializer(app).data
    await self.send_json({'action': 'create', 'data': app_json})

我决定在Application对象周围使用sync_to_async,因为错误消息突出显示了for循环行本身,而且我知道applicationSerializer会正常工作,因为我已经在其他异步方法中使用了它

这导致了TypeError: 'coroutine' object is not iterable

最后的想法

我对django通道和异步通道都很陌生,如果我知道通道将以异步为主,那么在我开始这个项目之前,我就会研究这个系统。

我查看了其他堆栈溢出帖子,并发现可能映射数据可能是一种解决方案,但我不能100%确定这是异步问题还是django-通道的问题。

我还能做些什么?

更新

根据Kens的建议,我继续尝试了以下代码:

代码语言:javascript
复制
   apps = await database_sync_to_async(Application.objects.all)()
   for app in apps:
       app_json = ApplicationSerializer(app).data
       print(app_json)

这返回了堆栈跟踪。

代码语言:javascript
复制
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\Devin\.virtualenvs\HomeAutomation-l9uhKhE0\lib\site-packages\channels\staticfiles.py", line 44, in __call__
    return await self.application(scope, receive, send)
  File "C:\Users\Devin\.virtualenvs\HomeAutomation-l9uhKhE0\lib\site-packages\channels\routing.py", line 71, in __call__
    return await application(scope, receive, send)
  File "C:\Users\Devin\.virtualenvs\HomeAutomation-l9uhKhE0\lib\site-packages\channels\sessions.py", line 47, in __call__
    return await self.inner(dict(scope, cookies=cookies), receive, send)
  File "C:\Users\Devin\.virtualenvs\HomeAutomation-l9uhKhE0\lib\site-packages\channels\sessions.py", line 254, in __call__
    return await self.inner(wrapper.scope, receive, wrapper.send)
  File "C:\Users\Devin\.virtualenvs\HomeAutomation-l9uhKhE0\lib\site-packages\channels\auth.py", line 181, in __call__
    return await super().__call__(scope, receive, send)
  File "C:\Users\Devin\.virtualenvs\HomeAutomation-l9uhKhE0\lib\site-packages\channels\middleware.py", line 26, in __call__
    return await self.inner(scope, receive, send)
  File "C:\Users\Devin\.virtualenvs\HomeAutomation-l9uhKhE0\lib\site-packages\channels\routing.py", line 150, in __call__
    return await application(
  File "C:\Users\Devin\.virtualenvs\HomeAutomation-l9uhKhE0\lib\site-packages\channels\consumer.py", line 94, in app
    return await consumer(scope, receive, send)
  File "C:\Users\Devin\.virtualenvs\HomeAutomation-l9uhKhE0\lib\site-packages\channels\consumer.py", line 58, in __call__
    await await_many_dispatch(
  File "C:\Users\Devin\.virtualenvs\HomeAutomation-l9uhKhE0\lib\site-packages\channels\utils.py", line 51, in await_many_dispatch
    await dispatch(result)
  File "C:\Users\Devin\.virtualenvs\HomeAutomation-l9uhKhE0\lib\site-packages\channels\consumer.py", line 73, in dispatch
    await handler(message)
  File "C:\Users\Devin\.virtualenvs\HomeAutomation-l9uhKhE0\lib\site-packages\channels\generic\websocket.py", line 196, in websocket_receive
    await self.receive(text_data=message["text"])
  File "C:\Users\Devin\.virtualenvs\HomeAutomation-l9uhKhE0\lib\site-packages\channels\generic\websocket.py", line 259, in receive
    await self.receive_json(await self.decode_json(text_data), **kwargs)
  File "D:\HomeAutomation\HomeAutomation\consumers.py", line 28, in receive_json
    for app in apps:
  File "C:\Users\Devin\.virtualenvs\HomeAutomation-l9uhKhE0\lib\site-packages\django\db\models\query.py", line 287, in __iter__
    self._fetch_all()
  File "C:\Users\Devin\.virtualenvs\HomeAutomation-l9uhKhE0\lib\site-packages\django\db\models\query.py", line 1308, in _fetch_all
    self._result_cache = list(self._iterable_class(self))
  File "C:\Users\Devin\.virtualenvs\HomeAutomation-l9uhKhE0\lib\site-packages\django\db\models\query.py", line 53, in __iter__
    results = compiler.execute_sql(chunked_fetch=self.chunked_fetch, chunk_size=self.chunk_size)
  File "C:\Users\Devin\.virtualenvs\HomeAutomation-l9uhKhE0\lib\site-packages\django\db\models\sql\compiler.py", line 1154, in execute_sql
    cursor = self.connection.cursor()
  File "C:\Users\Devin\.virtualenvs\HomeAutomation-l9uhKhE0\lib\site-packages\django\utils\asyncio.py", line 24, in inner
    raise SynchronousOnlyOperation(message)
django.core.exceptions.SynchronousOnlyOperation: You cannot call this from an async context - use a thread or sync_to_async.
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-11-30 14:11:45

这个代码sync_to_async(Application.objects.all)()创建了一个协同线,需要等待而不是直接使用。对于您的具体情况,最好先在For循环之外获取数据,然后继续。另外,您可能希望使用database_sync_to_async

代码语言:javascript
复制
from channels.db import database_sync_to_async

apps = await database_sync_to_async(Application.objects.all)()
for app in apps:
    app_json = ApplicationSerializer(app).data
    await self.send_json({'action': 'create', 'data': app_json})

另外,请注意,当序列化程序序列化应用实例时,请确保没有数据库查询。为此,请使用select_relatedprefetch_related预取可能需要的嵌套对象。

UPDATE:是的,由于一些Django方法(如.all() )的惰性特性,数据库实际上不会在调用该方法时被击中,而是在它被使用时被击中。强制它立即执行的一种常见方法是将查询集转换为列表。试试这个:

代码语言:javascript
复制
from channels.db import database_sync_to_async

apps = await database_sync_to_async(list)(Application.objects.all())
for app in apps:
    app_json = ApplicationSerializer(app).data
    await self.send_json({'action': 'create', 'data': app_json})
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65068192

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档