2013-08-01 66 views
0

另一个新手问题,我害怕。我有3个列表的这种形式。我们的目标是改变查询集的列表2(见视图代码)django - queryset差异 - 不按预期工作

form.py

class AddGameForm(forms.ModelForm): 
    won_lag = forms.ChoiceField(choices=[('1','Home') , ('2', 'Away') ],) 
    home_team = forms.ModelChoiceField(queryset=Player.objects.all(),required=True) 
    away_team = forms.ModelChoiceField(queryset=Player.objects.all(), required=True) 

    class Meta: 
     model = Game 
     fields =() 

view.py

def game_add(request, match_id): 
    # used to create a new Game 

    """ return http response page for creating a new Game """ 

    # Adding a new Game so just make a new one 
    game = Game() 

    # Get the match specified in the Querystring because we will need it to figure out  who the home team 
    # and away team are. 
    try: 
     match = Match.objects.get(id=match_id) 
    except Match.DoesNotExist: 
     # we have no object! do something 
     #todo: redirect to list match page? 
    pass 

    # get form 
    form = AddGameForm(request.POST or None, instance=game) 

    # Change the Queryset for Home and Away team to show only players that are on the team 
    # AND have not already played in a game so we need to get the "DIFFERENCE" between all 
    # team members and any players that have already played in the match 
    home_players = Player.objects.filter(team=match.home_team)   # All Home Team members 
    away_players = Player.objects.filter(team=match.away_team)   # All Away Team members 
    already_played_in_match_players = Game.objects.filter(match=match) # This is both home and away players 
                     # that have played in a Game on this match 

    form.fields['home_team'].queryset = home_players.exclude(pk__in=already_played_in_match_players) 
    form.fields['away_team'].queryset = away_players.exclude(pk__in=already_played_in_match_players) 
... 

在我的数据库我有以下几种:

Team 1 
    Player 1 
    Player 2 
Team 2 
    Player 3 

Match 1 
    no games 

因此当我打开表单时,如预期的那样,home_team列表显示Player1,Player2和away_team列表显示Player3

因此,我选择Player 1和Player3并保存游戏。 现在DB具有以下数据

Team 1 
    Player 1 
    Player 2 
Team 2 
    Player 3 

Match 1 
    Game 1 between Player1 and Player3 

我决定再添加一个比赛,我打开GameAddForm,并期望有HOME_TEAM列表只显示Player2和AWAY_TEAM列表中显示没有球员。

然而,在现实中,什么情况是,HOME_TEAM列表作为预期,的AWAY_TEAM列表中仍然显示播放器3.

我,为什么它能够正常工作,对主队完全糊涂了,但不是客队。

有什么建议吗?

在此先感谢您提供的任何指导。

回答

0

好的,算出来了。本质上,问题是与以下行:

already_played_in_match_players = Game.objects.filter(match=match) 

返回游戏,不玩家的查询集。

由于我想获得玩家,我必须从Player.object开始。这意味着我必须通过Game→Player1和Game→Player2关系向后查询。以下是文档中提到的内容:

Lookups that span relationships 

To span a relationship, just use the field name of related fields across models, separated by double underscores, until you get to the field you want 

... 

To refer to a “reverse” relationship, just use the lowercase name of the model. 

为了清楚起见,我将其分为几个步骤。

inner_query = Game.objects.filter(match=match) # Gets all games in this match 

然后我用下面的:

Player.objects.filter(player1__in=inner_query) 

基本上说,获得了由PLAYER1外键在innerquery查询集的任何游戏对象引用的所有的球员对象。

接下来我使用了| (管),以联盟PLAYER1和player2 一个QuerySet所以导致在这一行:

already_played_players = Player.objects.filter(player1__in=inner_query) | Player.objects.filter(player2__in=inner_query) 

这不得不所需的给我的谁在比赛中已经发挥所有球员名单的影响。

概要变化的

我改变有问题的行为以下:

... 

inner_query = Game.objects.filter(match=match) # All games in this match 

# Now use reverse relation to get the Player1 union Player2 to get all players who have played in this match so far 
already_played_players = Player.objects.filter(player1__in=inner_query) | Player.objects.filter(player2__in=inner_query) 

...