查询Django中所有类型的每个唯一类型的第n个最新条目

2024-06-16 13:12:28 发布

您现在位置:Python中文网/ 问答频道 /正文

我对这个问题进行了研究,并给出了每种类型的最新答案,例如this topic

不同之处在于,我希望获得每种类型的n最新项目,用于所有类型。现在我得到了所有的条目,然后在python中找到第n个最近的条目,这非常慢

例如

class CakeType(models.Model):
    name = models.CharField(max_length=40)

class CakeEntry(models.Model):
    cake_type = models.ForeignKey(CakeType, on_delete=models.CASCADE)    
    created = models.DateTimeField()

对于所有不同的/唯一的CakeType,我们如何得到最近的5个CakeEntry

我将数据库从MySQL迁移到PostgreSQL(做了很多工作),所以我可以使用Postgres的DISTINCT ON

阅读文档后,我尝试了以下操作:

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

    cake_entries = (
        CakeEntry.objects.order_by(
            '-created'
        ).annotate(
            rank=Window(
                expression=Rank(),
                partition_by=[F('cake_type_id')],
                order_by=F('created').desc(),
            ),
        ).filter(rank__lt=5)
    )

但是在没有等级/分区的情况下获得django.db.utils.NotSupportedError: Window is disallowed in the filter clause.,我不知道该怎么做


Tags: djangofrom类型dbbymodelmodelstype
1条回答
网友
1楼 · 发布于 2024-06-16 13:12:28

我看不到使用Window的方法,因为目标相互冲突:

为了避开过滤器问题,必须创建一个子查询。问题是,用作表达式(注释)的子查询应该返回1行,以便将特定的列组绑定到特定的外部引用,但窗口需要所有相关行的范围。如图所示:

# Pk 21 has rank 3
CakeEntry.objects.all().annotate(rank=rank).values("rank", "pk")[:3]
Out[11]: <QuerySet [{'pk': 2, 'rank': 1}, {'pk': 1, 'rank': 2}, {'pk': 21, 'rank': 3}]>
# Due to filter, pk 21 has rank 1, even though you seemingly filter after the annotation
CakeEntry.objects.all().annotate(rank=rank).values("rank", "pk").filter(pk=21)
Out[12]: <QuerySet [{'pk': 21, 'rank': 1}]>

我能想到的最接近的方法是:

class CakeEntryManager(models.Manager):
    def top5_per_type(self):
        cake_types = CakeType.objects.all()
        qs = self.get_queryset()
        results = qs.none()
        for ct in cake_types:
            results = results.union(qs.filter(cake_type=ct).order_by("-created")[:5])
        return results.order_by("cake_type", "-created")

相关问题 更多 >