Django Window 函数

Django Window functions

问题

如何使用 Django ORM 计算数据库中连续两行之间列的增量?

背景

我有以下型号:

class Foobar(models.Model):
    foo = models.IntegerField()

我想为数据库中的每一行计算 foo 之间的增量。我找到了Django's support for Window functions and the Lag() function。有了这些,我尝试了这样的事情:

Foobar.objects.annotate(delta=Window(expression=F('foo') - Lag('foo')))

出现以下错误:

Traceback (most recent call last):
  File "/usr/lib/python3.8/code.py", line 90, in runcode
    exec(code, self.locals)
  File "<input>", line 1, in <module>
  File "/home/user/.cache/pypoetry/virtualenvs/scraper-2Ye6bxs0-py3.8/lib/python3.8/site-packages/django/db/models/expressions.py", line 1275, in __init__
    raise ValueError(
ValueError: Expression 'CombinedExpression' isn't compatible with OVER clauses.

所以为了简化,我只是尝试用前一行的值注释每一行:

fs = Foobar.objects.annotate(prev=Window(expression=Lag('foo'))
for f in fs:
    print(model_to_dict(f))

不过,我的 print() 语句中的结果字典没有 'prev'。我错过了什么?使用 Lag() 计算每行之间的增量的正确方法是什么?

The resulting dicts in my print() statement don't have 'prev', though.

那是因为您正在使用 model_to_dict,它使用模型声明的字段到 return 字典,当然它对您通过查询注释的数据一无所知。如果您实际检查模型,该值确实会在其上进行注释:

fs = Foobar.objects.annotate(prev=Window(expression=Lag('foo'))

for f in fs:
    print(f.prev)

继续计算增量,您当然可以这样做,只是 F('foo') 需要在 外部 Window 表达式:

fs = Foobar.objects.annotate(delta=F('foo') - Window(expression=Lag('foo')))

for f in fs:
    print(f.delta)

Note: You seem to be using model_to_dict for some reason, perhaps for serializing data to use for an API? This is not really a great way to serialize models, instead you should look into using Django REST framework.