Получение ранга конкретного пользователя с помощью функции windows в djago

вот мой запрос, который дает мне рейтинг всех пользователей:

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};
        '''
    ```

Наборы квестов 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 queryset of Wallet objects
# of the desired user with the correct rank annotation applied
Вернуться на верх