0

恐怕另一个新手问题。我有这个带有 3 个列表的表格。目标是更改 2 个列表的查询集(请参阅视图中的代码)

表格.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 = ()

视图.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,然后保存游戏。现在数据库有以下数据

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 列表仍显示 Player 3。

我完全不明白为什么它对主队有效,但对客队无效。

有什么建议么?

提前感谢您提供的任何指导。

4

1 回答 1

0

好的,想通了。基本上问题出在以下行:

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

它返回Games的查询集,而不是Players

因为我想得到Players,所以我必须从 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)  

这实质上是说,在内部查询查询集中的任何 Game 对象中获取 player1 外键引用的所有 Player 对象。

接下来我使用了 | (管道)到 UNION 为 player1 和 player2 的查询集,因此它导致以下行:

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)

...
于 2013-08-01T17:12:27.700 回答