Django模型中的复杂派生属性

时间:2010-04-22 19:32:28

标签: sql django django-models sql-update user-defined-functions

我想要做的是为用户对内容进行投票的网站实施提交评分,就像在例如reddit(参见http://code.reddit.com/browser/sql/functions.sql中的'热'功能)。 编辑:最终,我希望能够检索根据其得分排列的任意长度提交的任意过滤列表。

我的提交模式目前跟踪上下投票总数。目前,当用户投票时,我创建并保存相关的投票对象,然后使用F()表达式更新Submission对象的投票总数。问题是我想同时更新提交的分数,但F()表达式仅限于简单的操作(它缺少对log(),date_part(),sign()等的支持。)

根据我对Django的有限经验,我可以在这里看到5个选项:

  1. 以某种方式扩展F()(尚未查看代码)以支持缺少的SQL函数;这是我的首选选项,似乎最适合Django框架

  2. 在我的数据库中定义一个评分函数(很像reddit的'hot'函数),让Django使用该函数的值作为得分字段的值;据我所知,#2是不可能的

  3. 将我的两步投票流程包含在一个适当的孤立交易中,以便我可以用Python计算投票总数,然后更新提交的投票总数,而不必担心在此期间可以添加/更改针对提交的另一次投票;我对采取这条路线犹豫不决,因为它似乎过于复杂 - 无论如何,这种情况下“适当孤立的交易”是什么?

  4. 使用原始SQL;我宁愿完全避免这种情况 - 如果我必须为这样一个常见的用例恢复SQL,那么ORM的重点是什么! (请注意,这来自喜欢sprocs的人,但是为了便于开发而使用Django。)

  5. (编辑:经过进一步讨论后添加)使用包含对我的函数调用的额外select参数计算得分;这会起作用,但会对数据库施加不必要的负担(将被迫计算每次查询运行时所做的每次提交的分数;缓存在这里可能会有所帮助,但它似乎仍然有点蹩脚的解决方法)

    < / LI>

    在我开始执行此任务以扩展F()(我甚至不确定是否可能)之前,我是否要重新发明轮子?有更标准的方法吗?这似乎是一个常见的用例,但在一小时的搜索中我还没有找到一个共同的解决方案......

    编辑:还有另一种选择:将数据库脚本中字段的默认值设置为包含我的函数的表达式。这不像#1那么灵活,但可能是解决问题的最快捷,最干净的方法(虽然我对扩展F()的初步调查看起来很有希望)。

1 个答案:

答案 0 :(得分:0)

为什么你不能对得分进行非规范化并每隔一段时间用投票对象重建一次?

如果你不能这样做,很容易制作一个'属性'函数作为评分的对象属性。

@property
def score(self):
    ... calculate score from Vote objects ...
    return score

我从来没有在像这样的属性上使用F(),但它是Python,所以我敢打赌它有效。

如果您正在使用django-voting(我推荐),您可以将#3放在经理的record_vote函数中,因为这就是所有投票交易的发生方式。