Django中的用户定义派生数据

2 投票
3 回答
1037 浏览
提问于 2025-04-15 11:30

我该如何让用户对一组数据应用他们自己的自定义公式,以便生成新的字段呢?

我正在开发一个Django应用,这个应用会为注册用户存储和处理大量数据。想象一下,每次请求可能会有100到10,000个传感器读数。我会用这些数据绘制图表,并展示包含这些数据的表格。我希望用户能够定义一组传感器,这些用户会在我的网站上注册(也就是说,他们对应着Django中的一个模型)。

我想让用户能够创建一些基于他们传感器数据的新字段(作为设置过程的一部分)。比如,用户可能知道他们家里的平均温度是(温度传感器1 + 温度传感器2)/ 2,并希望在图表上显示这个数据。他们可能还想要一些更复杂的公式,比如太阳能热水加热的计算是(出水温度 - 入水温度)* 流量 * 转换常数。然后我会为他们保存这些定义好的公式,供其他查看这组传感器数据的人使用。

我主要想知道的是,如何在系统中定义这个公式。难道我只需要一个用户定义的字符串来表示这个公式(比如100个字符长),然后自己解析它——把用户定义的部分替换成输入样本,然后称它为“toast”吗?

更新

最后我得到了我想要的答案:一种安全的方法来在服务器上评估存储的用户函数。当函数被定义时,在客户端也评估同样的函数将是让用户界面更直观的好方法。

3 个回答

0

另一个用户在C语言中问了一个类似的问题。在那个帖子里,Warren建议可以对公式进行解析,并将其转换成

(a + c) / b 

反向波兰表示法(reverse polish notation

a c + b / 

这样处理起来会更简单。

在这种情况下,你可以在保存公式模型的时候,拦截这个过程,并从用户定义的公式生成后缀表示法。一旦你得到了后缀表示法,写一个从左到右计算公式的循环就变得相对简单了。

至于在Django中的实现,核心问题是如何将不同的输入字段映射到公式中。一个简单的解决方案是,创建一个模型来表示派生字段,并使用多对多关系来定义每个输入的符号名称(比如“a”、“b”或“c”)。

如果性能真的很重要,你可以在将后缀公式应用到数据之前,进一步预处理一下。

2

首先,你需要想清楚你想支持哪些操作,比如加、减、乘、除、括号等等。然后,你可以用客户端的技术(也就是JavaScript)来处理这些操作,把结果应用到新的数据字段上。我觉得没必要在服务器端做这些,这样用户体验会更流畅、更愉快。

如果你让用户可以保存他们的公式,并在下次访问网站时重新加载这些公式,那么可以让他们的浏览器来完成所有的计算。只需要提供一些通用的方法,让他们可以把数据列加起来,这些数据是通过应用他们的公式生成的。

我想下一步可以让他们把这些操作应用到新生成的数据列上。

你有没有考虑过把他们的数据放到谷歌表格里?这样可以省去很多开发工作,因为谷歌表格已经允许你定义公式并应用到数据上。不过,我不太确定它对数据量的限制(也就是你可以放多少数据和进行多少操作)。

2

这要看你的客户是谁。

如果这是在互联网上对公众开放的,你就得自己解析表达式。你可以使用Python的编译器来编译Python语法。你也可以为Python语法的一个子集自己设计一个编译器。有很多例子可以参考,可以从ply项目开始。

如果这是在公司内部(“在防火墙后面”),你可以让他们提交一段Python代码,然后执行这段代码。

给他们一个环境,像这样:from math import *,让他们可以使用这些功能。

把他们提供的代码包裹在下面的代码中:

def userFunc( col1, col2, col3, ... ):
   result1= {{ their code goes here }}
   return result1

这样你就可以执行函数定义,并在没有出现问题的情况下使用这个定义的函数。

虽然有些人喜欢说exec是个“安全问题”,但这并不比用户分享密码,或者管理员做一些愚蠢的事情,比如删除重要文件或在你的程序运行时随机关掉电源,更严重。

只有在你允许任何人访问exec时,它才会成为安全问题。对于公司内部的应用,你知道用户是谁。好好培训他们。

撰写回答