我们假设我有以下模型:
class TestModel(models.Model):
some_integer = models.IntegerField()
我有这个模型的3个实例:
TestModel.objects.create(some_integer=100)
TestModel.objects.create(some_integer=50)
TestModel.objects.create(some_integer=20)
我想以某种方式注释queryset以获得以下结果:
for obj in TestModel.objects.annotate(difference=...):
print(obj.difference)
=> 50 # 100 - 50
=> 30 # 50 - 30
=> None # we don't have anything created after this record
有没有机会使用Django(2.0)查询集,或者我应该在Python中“手动”执行此操作?我们可以安全地假设对象按pk或某个日期排序,因此保留了排序。
基于这个Answer,如果你想用原始SQL做,你可以这样做:
SELECT *,
LEAD("some_integer") OVER(ORDER BY "id") AS "next_val",
"some_integer" - "next_val" AS "difference"
FROM "myapp_testmodel";
但是,从Django版本2.0
您可以使用Window Functions创建上述查询:
from django.db.models import Window, F
from django.db.models.functions import Lead
q = TestModel.objects.annotate(
next_val=Window(
expression=Lead('some_integer', offset=1, default=0),
order_by=F('id').asc()
),
difference=F('some_integer')-F('next_val')
)
注意:我使用0作为默认值(将应用于最后一项),以简化从单词中减去Null值导致的FieldError
的答案。你可以使用Django的Case查询处理最后一项的返回None。