Django 模型中的复杂派生属性

发布于 2024-08-29 21:32:58 字数 1231 浏览 6 评论 0原文

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

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

)使用 Django 的经验有限,我可以在这里看到 5 个选项:

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

  2. 在我的数据库中定义一个评分函数(很像 reddit 的“热门”函数),并让 Django 使用该函数的值作为分数值场地;据我所知,#2 不可能
  3. 将我的两步投票过程包装在一个适当隔离的事务中,以便我可以在 Python 中计算投票总数,然后更新提交的投票总数,而不必担心再次投票反对同时可以添加/更改提交内容;我对采取这条路线犹豫不决,因为它看起来过于复杂 - 在这种情况下,什么是“适当隔离的交易”?

  4. 使用原始 SQL;我宁愿完全避免这种情况——如果我必须针对像这样的常见用例恢复到 SQL,那么 ORM 的意义何在! (请注意,这是来自喜欢存储过程的人,但使用 Django 来简化开发。)

  5. (编辑:在进一步讨论后添加了此内容) 使用包含调用我的函数;这可以工作,但会给数据库带来不必要的负载(每次查询运行时都会被迫计算每次提交的分数;缓存在这里可能会有所帮助,但它看起来仍然是一个有点蹩脚的解决方法)

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

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

What I want to do is implement submission scoring for a site with users voting on the content, much like in e.g. reddit (see the 'hot' function in http://code.reddit.com/browser/sql/functions.sql). Edit: Ultimately I want to be able to retrieve an arbitrarily filtered list of arbitrary length of submissions ranked according to their score.

My submission model currently keeps track of up and down vote totals. Currently, when a user votes I create and save a related Vote object and then use F() expressions to update the Submission object's voting totals. The problem is that I want to update the score for the submission at the same time, but F() expressions are limited to only simple operations (it's missing support for log(), date_part(), sign() etc.)

From my limited experience with Django I can see 5 options here:

  1. extend F() somehow (haven't looked at the code yet) to support the missing SQL functions; this is my preferred option and seems to fit within the Django framework the best

  2. define a scoring function (much like reddit's 'hot' function) in my database, and have Django use the value of that function for the value of the score field; as far as I can tell, #2 is not possible

  3. wrap my two step voting process in a suitably isolated transaction so that I can calculate the voting totals in Python and then update the Submission's voting totals without fear that another vote against the submission could be added/changed in the meantime; I'm hesitant to take this route because it seems overly complex - what is a "suitably isolated transaction" in this case anyway?

  4. use raw SQL; I would prefer to avoid this entirely -- what's the point of an ORM if I have to revert to SQL for such a common use case as this! (Note that this coming from somebody who loves sprocs, but is using Django for ease of development.)

  5. (edit: added this after further discussion) compute the score using an extra select parameter containing a call to my function; this would work but impose unnecessary load on the DB (would be forced to calculate the score for every submission ever made every time the query ran; caching could help here, but it still seems like a bit of lame workaround)

Before I embark on this mission to extend F() (which I'm not sure is even possible), am I about to reinvent the wheel? Is there a more standard way to do this? It seems like such a common use case and yet in an hour of searching I have yet to find a common solution...

EDIT: There is another option: set the default value of the field in the database script to be an expression containing my function. This is not as flexible as #1, but probably the quickest and cleanest approach to solving the problem (although my initial investigation into extending F() looks promising).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

毁我热情 2024-09-05 21:32:58

为什么不能将分数非规范化并每隔一段时间用 Vote 对象重建它?

如果你做不到这一点,那么很容易创建一个“属性”函数来充当评分的对象属性。

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

我从来没有在这样的属性上使用过 F(),但它是 Python,所以我打赌它可以工作。

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

Why can't you just denormalize the score and reconstruct it with the Vote objects every once and a while?

If you can't do that, it is very easy to make a 'property' function that acts as an object attribute for scoring.

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

I've never used F() on a property like this, but it's Python, so I bet it works.

If you are using django-voting (which I recommend), you can put #3 in the manager's record_vote function since that's how all vote transactions take place.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文