Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/337.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在异步函数(通道使用者)Django中从数据库获取模型 总结_Python_Django_Asynchronous_Django Channels - Fatal编程技术网

Python 在异步函数(通道使用者)Django中从数据库获取模型 总结

Python 在异步函数(通道使用者)Django中从数据库获取模型 总结,python,django,asynchronous,django-channels,Python,Django,Asynchronous,Django Channels,您好,目前我正在开发一个应用程序,通过使用django通道将数据实时发送到前端。我已经能够对所有在页面打开时创建的模型执行此操作,但是我还无法在页面尚未打开时获取以前的模型 代码 下面是我第一次尝试让这个系统工作的一个例子,它将在消费者连接方法被激发时被调用,在连接被接受后,我将运行这个for循环 Application.objects.all()中的应用程序的: app_json=ApplicationSerializer(app).data 等待self.send_json({'action

您好,目前我正在开发一个应用程序,通过使用django通道将数据实时发送到前端。我已经能够对所有在页面打开时创建的模型执行此操作,但是我还无法在页面尚未打开时获取以前的模型

代码 下面是我第一次尝试让这个系统工作的一个例子,它将在消费者连接方法被激发时被调用,在连接被接受后,我将运行这个for循环

Application.objects.all()中的应用程序的
:
app_json=ApplicationSerializer(app).data
等待self.send_json({'action':'create','data':app_json})
当运行这段代码时,我会得到
django.core.exceptions.SynchronousOnlyOperation:不能从异步上下文调用此操作-使用线程或同步到异步。

这是有意义的,因为consumers connect方法是异步的,所以按照消息的建议,我继续使用了
sync\u to_async

对于同步到异步的应用程序(Application.objects.all)():
app_json=ApplicationSerializer(app).data
等待self.send_json({'action':'create','data':app_json})
我决定在应用程序对象周围使用
sync\u to\u async
,因为错误消息突出显示了for循环行本身,而且我知道applicationSerializer将正常工作,因为我在其他异步方法中使用过它

这将导致
TypeError:“coroutine”对象不可编辑

最后的想法 我对django通道和异步都是新手,如果我知道通道将大量基于异步,我会在开始这个项目之前研究这个系统

我看过其他堆栈溢出文章,发现映射数据可能是一个解决方案,但我不能100%确定这是一个异步问题还是django通道的问题

还有什么我可以试试的

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

apps=wait database\u sync\u to\u async(Application.objects.all)()
对于应用中的应用:
app_json=ApplicationSerializer(app).data
打印(app_json)
这返回了stacktrace

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.

这段代码
sync\u to_async(Application.objects.all)(
创建了一个需要等待而不是直接使用的协同程序。对于您的特定情况,最好先从For循环外部获取数据,然后继续。此外,您可能希望改用
数据库\u sync\u to \u async

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_related
prefetch_related
预取可能需要的任何嵌套对象

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

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})

你好我继续并尝试了您的建议,有趣的是,我得到了相同的错误
django.core.exceptions.SynchronousOnlyOperation:您不能从异步上下文调用此操作-使用线程或sync\u to\u async。
当我们声明
应用程序时,会引发这次错误回复,我继续用stacktrace@Timberghost_是的,我的错。查一下我的编辑,我很高兴能帮上忙。它不必是一个特定的列表,但这是常用的,因为列表类似于queryset,您仍然可以循环使用它。出于性能和可能的其他原因,Django不会执行它到达需要对象的位置的查询。要将queryset转换为Python列表,它需要从DB加载数据,从而执行查询。你可以在文件里读到它。