2016-08-21 34 views
1

私は結合モデルの属性を取得するための単一のクエリで最適なソリューションを見つけようとしています。単一のクエリでDjango select_related結合モデルの属性

class Player(models.Model): 
    first_name = models.CharField(max_length=30) 
    last_name = models.CharField(max_length=30) 
    season_team = models.ForeignKey(SeasonTeam, related_name='players', blank=True, null=True) 
    leagues = models.ManyToManyField(League, related_name='players', through='PlayerLeague') 


class League(models.Model): 
    name = models.CharField() 


class PlayerLeague(models.Model): 
    player = models.ForeignKey(Player) 
    league = models.ForeignKey(League) 
    stamina = models.PositiveSmallIntegerField(_('Stamina'), default=100) 


class Team(models.Model): 
    name = models.CharField(max_length=30, validators=[ 
     RegexValidator(regex='^[a-zA-Z0-9\s]+$', message=_('name must contain only chars and numbers'),), ]) 
    players = models.ManyToManyField(Player, blank=True, related_name='teams') 
    league = models.ForeignKey(League, related_name='teams') 

は、これは私がスタミナメソッドを追加することでスタミナをプリロードするget_context_dataにロードされているすべてのプレイヤーが

class FormationUpdateView(AjaxResponseMixin, FormationRequirementsMixin, UpdateView): 
    model = Formation 
    template_desktop = 'hockey/formation/form.html' 
    template_mobile = 'hockey/formation/mobile/form.html' 
    form_class = FormationForm 

    def get_initial(self): 
     self.initial = {'active': True} 
     return self.initial.copy() 

    def get_context_data(self, **kwargs): 
     context = super(FormationUpdateView, self).get_context_data(**kwargs) 
     team = Team.objects.select_related('league').get(formations=self.kwargs['pk']) 
     context['players'] = Player.objects.filter(teams=team).all() 
     context['league'] = team.league 
     return context 

    def get_queryset(self): 
     return Formation.objects.select_related() 

    def get_template_names(self): 
     if 'Mobile' in self.request.META['HTTP_USER_AGENT']: 
      return self.template_mobile 
     return self.template_desktop 

私の最初の解決策だった属性たいビューです:

私は、次のモデルとの関係を持っていますプレイヤークラスへ:

def stamina(self, league): 
    p_l = self.leagues.through.objects.filter(league=league)[0] 
    return p_l.stamina 

私はこの解決策が嫌いです原因は、各プレイヤーのスタミナ値を照会することです。

答えて

2

あなたのモデルは少し心ねじれていますが、そのようなことは、データベースを押すことなく選手のスタミナを取得するには要求

from django.db.models import Q, F, Prefetch 

... 

def get_context_data(self, **kwargs) 
    context = super(FormationUpdateView, self).get_context_data(**kwargs) 
    team = (Team.objects 
    .select_related('league') 
    .prefetch_related(
     Prefetch(
      'players', 
      queryset=(Player.objects.filter(leagues=F('leagues')) 
         .prefetch_related('playerleagues')) 
     ) 
    ).get(formations=self.kwargs['pk'])) 
    context['players'] = team.players.all() 
    context['league'] = team.league 
    return context 

の数を最小限に抑える必要があります任意の助けてくれてありがとう再び。

players[0].playerleagues.all()[0].stamina 
+0

私はできるだけ早く回答を試みます。あなたは、モデルが心をひねっていると言うと、より具体的になりますか? – Pietro

関連する問題