Python 如何将Django ORM与面板一起使用? 总结

Python 如何将Django ORM与面板一起使用? 总结,python,django,asynchronous,panel,Python,Django,Asynchronous,Panel,我想在应用程序中实现一个交互式仪表板 使用数据库中的数据 首先,我遵循了panel文档中的方法,它在我的Django项目中运行良好。在该示例中,数据在一个简单函数中计算,并显示一个曲线图。 我可以使用这些小部件并获得预期的结果 对于我的应用程序,我希望根据用户在UI中选择的日期范围聚合数据库中的数据,而不是计算没有外部依赖关系的数据。因此,据我所知,我必须在param.Parametrized实例中收集这些数据 因此,我尝试在数据库ORM上使用查询,而不是计算值 我试过的 为了保持这里的简单性并

我想在应用程序中实现一个交互式仪表板 使用数据库中的数据

首先,我遵循了panel文档中的方法,它在我的Django项目中运行良好。在该示例中,数据在一个简单函数中计算,并显示一个曲线图。 我可以使用这些小部件并获得预期的结果

对于我的应用程序,我希望根据用户在UI中选择的日期范围聚合数据库中的数据,而不是计算没有外部依赖关系的数据。因此,据我所知,我必须在
param.Parametrized
实例中收集这些数据

因此,我尝试在数据库ORM上使用查询,而不是计算值

我试过的 为了保持这里的简单性并保持不变,我在Django应用程序(称为
仪表板
)中为正弦值创建了一个模型:

来自django.db导入模型的

类别值(models.Model):
x=models.FloatField()
y=模型。FloatField()
并插入了一些值:

DELETE FROM dashboard_sinevalue;
INSERT INTO dashboard_sinevalue (id,x,y) VALUES (1,1,1);
INSERT INTO dashboard_sinevalue (id,x,y) VALUES (2,2,4);
INSERT INTO dashboard_sinevalue (id,x,y) VALUES (3,3,9);
然后,我将正弦值的计算替换为从数据库请求值的代码:

from.models导入值
[...]
类正弦波(参数化):
[…与示例中相同…]
def正弦(自):
#旧:计算值
#x=np.linspace(0,4*np.pi,self.N)
#y=自振幅*np.sin(自频率*x+自相位)+自偏移
#新:改为从数据库获取
all_sines=SineValue.objects.all()
x、 y=zip(*所有正弦值列表('x','y'))
返回x,y
在面板外,我可以毫无问题地获得值

但是,在像这样更改正在运行的示例后,我得到以下错误:

django.core.exceptions.SynchronousOnlyOperation: You cannot call this from an async context - use a thread or sync_to_async.
经过一点研究,我发现这是意料之中的,因为我试图 在异步环境中执行同步代码。Django 3有这样的方法:

所以我试着使用,甚至更好, 似乎是为这个案子做的。我现在的问题是,构造函数

类正弦波(参数化):
[…与示例中相同…]
定义初始化(self,**参数):
超级(正弦波,自)。\uuuuu初始值(**参数)
x、 y=self.sine()
self.cds=ColumnDataSource(data=dict(x=x,y=y))
self.plot=图形(绘图高度=400,绘图宽度=400,
tools=“十字线、平移、重置、保存、滚轮\u缩放”,
x_范围=self.x_范围,y_范围=self.y_范围)
self.plot.line('x','y',source=self.cds,线宽=3,线α=0.6)
已调用方法
self.sine()
。所以当我像这样装饰
sine()
方法时

从channels.db导入数据库\u sync\u到\u async
[...]
@数据库\u同步\u到\u异步
def正弦(自):
all_sines=SineValue.objects.all()
x、 y=zip(*所有正弦值列表('x','y'))
#x=np.linspace(0,4*np.pi,self.N)
#y=自振幅*np.sin(自频率*x+自相位)+自偏移
返回x,y
我需要在任何地方都将其称为coroutine,因此我也在构造函数中使用
wait

类正弦波(参数化):
[...]
定义初始化(self,**参数):
超级(正弦波,自)。\uuuuu初始值(**参数)
x、 y=等待自我。正弦()
[...]
这是不可能的:

SyntaxError: 'await' outside async function
我原以为在使用
面板时这是一项常见的任务,但我还没有找到
解决方案还没有找到。这似乎是相关的,我做了一些实验
使用
从concurrent.futures导入ThreadPoolExecutor
如讨论中所述。最后,我得到了一个开始的信息:

You cannot call this from an async context - use a thread or sync_to_async
问题 所以我的问题是:

  • 是否可以在面板小部件中使用Django ORM数据库查询的结果
  • 如何更改此项的设置?decorator
    @database\u sync\u to\u async
    是要走的路还是别的什么
  • 如果小部件发生更改,是否可能触发新的数据库请求,例如 在queryset上放置过滤器
  • 如果这是不可能的,你有其他想法如何实现一个交互式的 使用Django的仪表板,以便显示数据库请求的结果

关于异步/等待,我是一个初学者。谢谢你的提示。

好的,我用一个相对简单的解决方案解决了这个问题

在我的代码中,我没有从ORM函数返回任何东西,我只是在操作自变量,我很高兴它能够运行异步(而不是等待它完成),所以我像

import asyncio

def __init__(self, **params):
    super(SineWave, self).__init__(**params)
    coroutine = self.sine()
    asyncio.create_task(coroutine)

@database_sync_to_async
def sine(self):
    all_sines = SineValue.objects.all()
    x,y = zip(*all_sines.values_list('x', 'y'))
    self.x = np.linspace(0, 4 * np.pi, self.N)
    self.y = self.amplitude * np.sin(self.frequency * x + self.phase) + self.offset
    # return x, y
    
如果需要同步返回结果,可以尝试

def __init__(self, **params):
    super(SineWave, self).__init__(**params)
    coroutine = self.sine()
    task = asyncio.create_task(coroutine)
    x,y = task.result()

这里有更多的上下文基本上这是在向bokeh应用程序运行的当前事件循环中添加异步任务。

我遇到了完全相同的问题,我正在积极尝试解决它,如果找到解决方案,我会报告。