2010-04-22 64 views
0

我想要做的是为用户投票内容的网站实现提交评分,就像在例如。 reddit(请参阅http://code.reddit.com/browser/sql/functions.sql中的“热门”功能)。 编辑:最终,我希望能够检索任意长度的提交任意长度根据他们的分数排序的任意过滤列表。Django模型中复杂派生的属性

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

我与Django的有限的经验,我可以看到5个选项的位置:

  1. 延长F()以某种方式(没有看过的代码还)支持失踪SQL函数;这是我的首选选项,似乎适合Django框架内最好的

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

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

  4. 使用原始SQL;我宁愿完全避免这种情况 - 如果我必须为这样的常见用例恢复到SQL,那么ORM的意义何在! (请注意,这从别人谁喜欢存储过程,但未来是使用Django,便于开发的。)

  5. (编辑:经过进一步的讨论加入这个)使用包含一个呼叫一个额外的选择参数计算的分数我功能;这会工作,但会对数据库施加不必要的负载(将被迫计算每次提交的每次提交的分数,缓存可能会有所帮助,但它似乎仍然有点蹩脚的解决方法)

在我开始执行这个扩展F()的任务之前(我不知道甚至可能),我是否要重新发明轮子?有没有更标准的方法来做到这一点?这似乎是这样一个共同的用例,但在搜索我还没有找到一个共同的解决办法的一个小时......

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

回答

0

为什么你不能每隔一段时间就对表情进行非规范化处理并重构它?

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

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

我从来没有使用F()这样的属性,但它是Python,所以我敢打赌它的工作原理。

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

+0

虽然这是真的,但我可以按照你所说的去规范化,这对我来说是一个非常基本的DBMS用例,如果Django不支持它,那么我至少会努力为它添加我自己的支持,时间和简化允许(例如没有多数据库兼容性)。基本工作在F()表达式中。 派生Pythonic属性不起作用;对不起,我忽略了一项要求:我希望能够检索任意类别,标签等热门提交列表。 Django-voting很不错,但我更愿意避免选项#3,因为它最终是一种解决方法。 – rabidpebble 2010-04-22 20:58:44