django-queryset差异-没有像我预期的那样工作
恐怕又是一个新手问题。我有这张有三张清单的表格。目标是更改其中两个列表的查询集(请参见视图中的代码) form.pydjango-queryset差异-没有像我预期的那样工作,django,django-queryset,Django,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=Tr
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 = ()
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)
...
view.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 = ()
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
Player.objects.filter(player1__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)
...
因此,当我打开表单时,正如预期的那样,主队列表显示球员1、球员2,客队列表显示球员3
所以我选择玩家1和玩家3,然后保存游戏。
现在DB有以下数据
Team 1
Player 1
Player 2
Team 2
Player 3
Match 1
Game 1 between Player1 and Player3
我决定添加另一个游戏,所以我打开GameAddForm,希望主队列表只显示玩家2,客队列表不显示玩家
然而,在现实中,发生的事情是主队名单按预期行事,但客队名单仍然显示球员3
我完全搞不懂为什么它对主队有效而对客队无效
有什么建议吗
提前感谢您提供的任何指导。好的,我想好了。基本上,问题出在以下几行:
already_played_in_match_players = Game.objects.filter(match=match)
它返回的查询集为游戏,而不是玩家
因为我想得到玩家,所以我必须从Player.object开始。这意味着我必须在游戏中提问→ 玩家1和游戏→ 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
然后我使用了以下方法:
Team 1
Player 1
Player 2
Team 2
Player 3
Match 1
no games
Player.objects.filter(player1__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)
...
本质上就是说,在innerquery查询集中的任何游戏对象中,获取player1 foreignkey引用的所有玩家对象
接下来,我使用|(管道)为player1和player2合并查询集
因此,它产生了这一行:
already_played_players = Player.objects.filter(player1__in=inner_query) | Player.objects.filter(player2__in=inner_query)
这给了我一份已经参加过比赛的所有球员的名单
变更摘要
我将违规行更改为以下内容:
Team 1
Player 1
Player 2
Team 2
Player 3
Match 1
no games
Player.objects.filter(player1__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)
...