问题描述
我有以下型号:
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)