如何使用第二个模型中的复杂数据对Django模型进行排序?

时间:2010-08-22 08:23:19

标签: django sorting django-models django-queryset

我有3个django模型(本例简化):

class Fighter (models.Model):
    name = models.CharField(max_length=100)
    weight_class = models.ForeignKey(WeightClass, related_name="fighter_weight_class")

class Bout (models.Model):
    fighter_1 = models.ForeignKey(Fighter, related_name="bout_fighter_1")
    fighter_2 = models.ForeignKey(Fighter, related_name="bout_fighter_2")
    winner = models.ForeignKey(Fighter, related_name="bout_winner", blank=True, 
        null=True, help_text='Leave blank for draw.') 
    date = models.DateField()
    cancelled = models.BooleanField()

class WeightClass (models.Model):
    name = models.CharField(max_length=100)

我希望能够根据他们的统计数据列出战士。我创造了这些 功能(可以工作)来计算他们的胜利,损失和平局:

def get_bouts_with_fighter (fighter):
 return Bout.objects.filter(fighter_1 = fighter) | \
  Bout.objects.filter(fighter_2 = fighter) 

def get_fighter_wins (fighter):
 return Bout.objects.filter(winner=fighter)

def get_bouts_fought_not_won (fighter):
 return get_bouts_with_fighter(fighter) \
  .exclude(cancelled=True) \
     .exclude(date__gt = datetime.datetime.now())

def get_fighter_losses (fighter):
 return get_bouts_fought_not_won(fighter)\
  .exclude(winner=fighter)\
  .exclude(winner=None)

def get_fighter_draws (fighter):
 return get_bouts_fought_not_won(fighter)\
  .filter(winner=None)

但是现在,当对视图的输出进行排序时,我遇到了两个问题:

  1. “排序”既不正确也不一致。
  2. 在排序期间,我正在失去战斗机的名字
  3. 这是当前代码(如果不执行排序,则输出正确):

    def list(request, sort=None):
    
        class WeightGroup:
            """
            Internal class to keep data organized by weight class.
            """
            weight_class = None
            fighters = None
    
            def win_sort (self):
                wins = []
                winners = []
    
                for fighter in self.fighters:
                    wins.append((fighter.id, get_fighter_wins(fighter)),)
                for win in (sorted(wins, key=lambda f: f[1], reverse=True)):
                    winners.append(Fighter.objects.filter(id=win[0])) #build winner list by score
    
                self.fighters = winners
    
            def loss_sort (self):
                #TO DO:
                pass
    
            def draw_sort (self):
                #TO DO:
                pass
    
    
        title = 'Fighters'
        weight_groups = []
    
        for weight_class in WeightClass.objects.all():
            weight_group = WeightGroup()
            weight_group.weight_class = weight_class
            weight_group.fighters = Fighter.objects.filter(weight_class=weight_class)
            weight_groups.append(weight_group) 
    
        if sort in ['wins', 'losses', 'draws']:
            title += ', sorted by ' + sort
            for weight_group in weight_groups:
                if (sort == 'wins'): weight_group.win_sort()
                if (sort == 'losses'): weight_group.loss_sort()
                if (sort == 'draws'): weight_group.draw_sort()
    
        return render_to_response ('fighters/list.html',{
            'title': title, 
            'weight_groups':weight_groups
        })
    

    任何建议我如何让这个工作将不胜感激!

1 个答案:

答案 0 :(得分:0)

我设法解决了这两个问题:

  1. 我追加了胜利的集合,而不是该列表的“长度”。 我需要改变这个:

    wins.append((fighter.id,get_fighter_wins(战斗机)),)

    为:

    wins.append((fighter.id,len(get_fighter_wins(战斗机))),)

  2. 我正在构建一个查询集列表,而不是一个对象列表。 我需要改变这个:

    winners.append(Fighter.objects.filter(id = win [0]))

    为:

    winners.append(Fighter.objects.get(id = win [0]))

  3. (向我的朋友Attila干杯,向我解释了第二个问题。)

    顺便说一句,我的最终代码不使用三个单独的函数。相反,我这样做了:

        .
        .
        .
    
    class WeightGroup:
        .
        .
        .
                def sort (self, sort_function):
                    scores = []
                    scorers = []
    
                    for fighter in self.fighters:
                        scores.append((fighter.id, len(sort_function(fighter))),)
                    for score in (sorted(scores, key=lambda f: f[1], reverse=True)):
                        scorers.append(Fighter.objects.get(id=score[0])) 
    
                    self.fighters = scorers
        .
        .
        .
            if sort in ['wins', 'losses', 'draws']:
                title += ', sorted by ' + sort
                for weight_group in weight_groups:
                    if (sort == 'wins'): weight_group.sort(get_fighter_wins)
                    if (sort == 'losses'): weight_group.sort(get_fighter_losses)
                    if (sort == 'draws'): weight_group.sort(get_fighter_draws)
        .
        .
        .