Django-如何使用 F 表达式获取查询集中的元素索引

问题描述

我有以下型号:

class Topic(models.Model):
    title = models.CharField(max_lenght=32)
    # Some other fields.

class Thread(models.Model):
    topic = models.ForeignKey(Topic,related_name=threads',on_delete=models.CASCADE)
    # some other fields

class Message(models.Model):
    thread = models.ForeignKey(Thread,related_name='messages',on_delete=models.CASCADE)
    text = models.TextField()
    created = models.DateTimeField(auto_Now_add=True)

我想通过 Thread 计算查询集中每个 F() 中每个元素的索引。例如,如果在 Thread 1 中有 5 条消息,我希望消息的索引为 1 到 5。
我的代码不起作用。 代码如下:

from django.models import Count,Q,F
messages = Message.objects.filter(...).annotate(
    index=Count('id',filter=Q(thread_id=F('thread_id'),created__lt=F('created'))) + 1
).annotate(
    page=F('index') / 20
)

这为所有元素返回相同的索引。例如,这将为查询集中的所有项目返回 index=5。
如何计算查询集中元素的索引?

更新:
考虑以下事项:
我有 1000 条消息。
页面大小 = 20。
消息页数 = 1000 / 20 = 50

现在,如果我过滤 searched = Message.objects.filter(text__contains="hello"),将在 searched 查询集中返回 5 条消息。
我的最终目标是找到每条消息在哪个页面? (我有 50 页)

解决方法

如果您希望由数据库完成此操作,您需要查看 Window 函数,特别是 Rank 函数 (https://docs.djangoproject.com/en/3.2/ref/models/database-functions/#rank),它允许您根据分组(如按线程)为每一行分配一个数字

这可能会奏效:

from django.db.models import Window,F
from django.db.models.functions import Rank

index = Window(
    expression=Rank(),order_by=F('created'),partition_by=F('thread'),)
Message.objects.annotate(index=index)