python - 过滤 Django 时保持带注释的排名

标签 python django postgresql window-functions

我有一个过滤查询集,其中我根据特定顺序注释了每个对象的排名。

当我执行其他过滤器时,例如按排名更改顺序保持不变。执行新的 .filter() 时出现问题

我在页面上有一个搜索功能,可以过滤对象标题后的结果。但是当我这样做时,带注释的排名值会根据新查询中的结果数量而变化,而不是保持其原始值。

举例说明:

这是我的原始查询:

choices_filter = Choice.objects.filter(tournament=pk).annotate \
    (rank=RawSQL("RANK() OVER(ORDER BY winrate DESC, pickrate DESC, times_played)", []))

这会返回一个像这样的查询集:

Rank        Title         Winrate      
1...........Apple...........55%
2...........Pear............47%
3...........Banana..........44%
4...........Orange..........35%
5...........Watermelon......31%

如果我执行 .order_by('title') 我会得到以下预期结果:

Rank        Title         Winrate      
1...........Apple...........55%
3...........Banana..........44%
4...........Orange..........35%
2...........Pear............47%
5...........Watermelon......31%

但是如果我改为执行 .filter(title__icontains='an') 我会得到这个:

Rank        Title         Winrate      
1...........Banana..........44%
2...........Orange..........35%

而不是想要的:

Rank        Title         Winrate      
3...........Banana..........44%
4...........Orange..........35%

我对 Django 和 python(和数据库)的经验还不够,无法自行浏览。我花了一段时间才弄清楚如何注释排名并让它与分页等一起工作。

如果相关,这是我的完整 View 代码(我使用的是 Django Rest Framework 和 APIviews):

class GameDetailFilterView(APIView, PaginationHandlerMixin):
    permission_classes = (AllowAny, )
    pagination_class = FullPagination
    serializer_class = ChoiceSerializer

    def get(self, request, pk, *args, **kwargs):
        choices_filter = Choice.objects.filter(tournament=pk).annotate \
            (rank=RawSQL("RANK() OVER(ORDER BY winrate DESC, pickrate DESC, times_played)", []))
        filter_condition = request.session['filter_condition']
        if filter_condition is not None:
            choices = choices_filter.filter(title__icontains=filter_condition)
        else:
            choices = choices_filter.order_by('rank')

        page = self.paginate_queryset(choices)

        if page is not None:
            serializer = self.get_paginated_response(self.serializer_class(page,
                                                                           many=True).data)
        else:
            serializer = self.serializer_class(choices, many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)

最佳答案

您可以使用 django-cte图书馆

from django_cte import CTEManager, With

# models.py
class Choice(Model):
    objects = CTEManager()
    # ... other fields like tournament

# query 
cte = With(
Choice.objects.filter(tournament=pk).annotate \
(rank=RawSQL("RANK() OVER(ORDER BY winrate DESC, pickrate DESC,times_played)", [])))
qs = cte.queryset().with_cte(cte).filter(title__icontains='an')

然后关注这个 link .

关于python - 过滤 Django 时保持带注释的排名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65046994/

相关文章:

django - 使 'collectstatic' 找到更新的文件

python - 如何为使用 django、docker 和 mysql 的项目设置最佳配置?

ruby - postgres 本地主机连接不良

python - 在 float 数组中找到最小值

javascript - 沿弧线寻找点

python - 在django模型中使用python super 函数

database - Django-queryset 每个字段获取一个对象=foo

sql - 如果外键的列设置为 false,Postgres 将删除一行

sql - 如何通过客户端库 (Postgres) 在 SQL 查询中将元组(不是数组)作为 WHERE 约束参数传递?

Python将文件保存到根子文件夹