在 djago 中使用 Windows 功能获取特定用户的排名

问题描述 投票:0回答:1

这是我的查询,它给出了所有用户的排名:

rank = Wallet.objects.filter(type=0, space_id=space.id).annotate(
            rank=Window(
                expression=DenseRank(),
                order_by=F('point_amount').desc(),
            )
        ).order_by('rank').values("user__id","user__username","rank")

但是我怎样才能获得这个查询中特定用户的排名?(我不想处理这个python)

我已经尝试过这个:

rank = Wallet.objects.filter(type=0, space_id=space.id, user_id=user.id).annotate(
            rank=Window(
                expression=DenseRank(),
                order_by=F('point_amount').desc(),
            )
        ).order_by('rank').values("user__id","user__username","rank")

但它给了我排名 1,这是不正确的

注意: 这个原始查询给了我正确的答案,但我不知道如何将其转换为 django orm 查询

query = f'''
            SELECT
                FIND_IN_SET(
                    `transaction_wallet`.`point_amount`,
                    (
                        SELECT
                        GROUP_CONCAT(`transaction_wallet`.`point_amount` ORDER BY `transaction_wallet`.`point_amount` DESC)
                        FROM `transaction_wallet`
                        WHERE `transaction_wallet`.`type` = 0 AND `transaction_wallet`.`space_id` = {space.id}
                    )
                ) AS `rank`
            FROM
                `transaction_wallet`
            WHERE
                `transaction_wallet`.`type` = 0 AND `transaction_wallet`.`space_id` = {space.id} AND `transaction_wallet`.`user_id` = {self.id};
        '''
    ```
python django orm
1个回答
0
投票

Django 查询集是惰性的。在需要时对它们进行评估。这意味着当执行查询时,

user_id
过滤器将查询集限制为单个对象,然后评估窗口函数。结果是
rank
1
值。 要解决此问题,您必须首先构建不带
user_id
过滤器的查询,让 django 执行查询(包括注释),然后应用
user_id
过滤器。

# Step 1: Build the annotated query
rank = (Wallet
        .objects
        .filter(type=0, space_id=space.id)
        .annotate(rank=Window(expression=DenseRank(),
                              order_by=F('point_amount').desc())
        .order_by('rank'))
# Step 2: Evaluate the query
rank.count()

# Step 3: Now apply the filter
ranked_user_wallet = rank.filter(user_id=user.id)

# Now ranked_user_wallet is a single Wallet object of the desired user
# with the correct rank annotation applied
© www.soinside.com 2019 - 2024. All rights reserved.