Нахождение позиции определенной записи в запросе в DJango ORM
У меня есть такая модель Django,
class Account(models.Model):
user = models.OneToOneField(User, null=True, on_delete=models.CASCADE)
name = models.CharField(max_length=255, null=True)
ratings = models.FloatField(default=1000)
Что я хочу сделать - это человек, который вошел в систему, я хочу найти его rank
на основе рейтинга пользователя. То есть, мне нужно найти позицию указанной строки в запросе, где записи будут упорядочены по колонке ratings
, в порядке убывания.
Я нашел хорошее решение здесь, но оно, к сожалению, не работает для меня. https://stackoverflow.com/a/51317266/11454905
Используя эту же концепцию, я набрал следующий запрос,
player = Account.objects.filter(user = request.user).annotate(rank = Window(expression=Rank(), order_by=F('ratings').desc()),)[0]
Но независимо от того, какой пользователь, он всегда возвращает player.rank
как 1
, что не соответствует действительности. Я не могу понять, что я делаю неправильно и как я могу это исправить.
Если вы делаете это только для одного объекта User, то вы можете просто подсчитать пользователей, у которых рейтинг выше, чем у текущего пользователя - я заметил, что вы используете filter(user=request.user)
, который на самом деле не получает объект одного пользователя. Вообще говоря, вы должны использовать get()
, хотя здесь вы можете просто сделать request.user
.
rank = Player.objects.filter(ratings__gte=request.user.ratings).count()
Что касается аннотирования набора пользователей, можно использовать выражения Window()
и DenseRank()
:
from django.db.models import Window
from django.db.models.functions import DenseRank
players = Player.objects.order_by('ratings').annotate(
rank=Window(
expression=DenseRank(),
order_by=F('ratings').desc()
)
)