2015-11-13 2 views
0

У меня есть следующие модели:как заказать по модельной функции в Джанго

class Player(models.Model): 
    user = models.OneToOneField(User, related_name="player") 
    first_name = models.CharField(max_length=128) 
    last_name = models.CharField(max_length=128) 

    def point_total(self): 
     playerAchievements = PlayerAchievement.objects.filter(player=self) 
     score = 0 
     for p in playerAchievements: 
      score += p.achievement.value 
     return score 

    def full_name(self): 
     return self.first_name + ' ' + self.last_name 

    def rank(self): 
     print '---' 
     players = Player.objects.filter(team__league=self.team.league).order_by(self.point_total()) 
     print self.first_name 
     position = 0 
     for p in players: 
      position +=1 

      if p.id == self.id: 
       return str(position) 
     return '0' 

Ничто не обрабатывается мимо этой линии:

players = Player.objects.filter(team__league=self.team.league).order_by(self.point_total()) 

Я также попытался это, но имеет тот же эффект:

players = self.objects.filter(team__league=self.team.league).order_by('player__point_total') 

Как я могу заказать функцию общей точки, чтобы я мог определить ранг каждого игрока?

+0

Где находится поле 'team' в вашей модели' Player'? Это не сработает, это ваш фактический код? –

ответ

2

Функция order_by работает только с полями в базе данных, поэтому вызов функции не будет работать.

Что вы можете сделать, однако annotate функция с Count агрегации через ForeignKey и затем order_by что:

from django.db.models import Sum 

players = Player.objects.filter(team__league=self.team.league) 
players = players.annotate(achievement_sum=Sum('playerachievement_set__achievement__value')) 
players = players.order_by('achievement_sum') 
+1

Думаю, ему нужна 'Sum', а не' Count'. И я думаю, что его 'playerachievement__achievement__value' в соответствии с его кодом –

+0

@ CésarBustíos Упс, вы правы. –

+1

Это красивее, чем поэзия. Спасибо @LegoStormtroopr. Спасибо за помощь CésarBustíos – Atma

0

Вы не можете заказать querysets от методов и свойств в Джанго, вы должны сделать сортировка самостоятельно в python.

players_to_sort = Player.objects.filter(team__league=self.team.league) 
sorted_player = sorted(players_to_sort, key=lambda player: player.point_total()) 
+0

Это безумно неэффективно, если есть много возвращенных объектов (или много одновременных пользователей), так как это приведет к тому, что все объекты будут отсортированы Python, а каждый объект, имеющий вызов базы данных, достижение_sum' каждого игрока. –

+0

@LegoStormtroopr Таким образом, yep, но вы можете преобразовать point_total в cached_property, поэтому вы избежите запроса БД. Кстати, ваше решение лучше. – levi