2010-08-22 5 views
0

J'ai 3 modèles django (simplifié pour cet exemple):Comment trier mon modèle Django en utilisant des données complexes d'un second modèle?

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) 

Je voudrais être en mesure d'énumérer les combattants par leurs stats. J'ai créé ces fonctions (qui travaillent) pour calculer leurs victoires, défaites et Match nul:

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) 

Mais maintenant, quand vient à la sortie de tri pour la vue, je vais avoir deux problèmes:

  1. Le "tri" n'est ni correct ni cohérent.
  2. Au cours de ce genre, je suis en train de perdre le nom de combattant

Voici le code actuel (la sortie est correcte si aucun tri est effectué):

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 
    }) 

Toute suggestion comment je peux obtenir ceci pour travailler sera apprécié!

Répondre

0

J'ai réussi à résoudre les deux problèmes:

  1. je la collection de Annexer des victoires, et non pas la « longueur » de cette liste. je devais changer ceci:

    wins.append ((fighter.id, get_fighter_wins (combattant)),)

    à:

    wins.append ((fighter.id, len (get_fighter_wins (combattant))),)

  2. Je construisais une liste de querysets, pas une liste d'objets. je devais changer ceci:

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

    à:

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

(Bravo à mon ami Attila qui a expliqué la deuxième question pour moi.)

BTW, mon code final n'utilise pas trois fonctions distinctes. Au lieu de cela, j'ai fait ceci:

. 
    . 
    . 

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) 
    . 
    . 
    .