Django足球联赛统计API报错:无法识别home_team_goals字段
解决Django足球联赛应用的进球数、积分统计错误问题
问题根源
你遇到的Cannot resolve keyword 'home_team_goals' into field错误,是因为你的Match模型没有直接定义home_team_goals和away_team_goals字段,之前的统计逻辑错误地尝试直接调用这些不存在的字段。需要通过关联的Goal模型来计算每场比赛的主客队进球数,再基于此推导胜场、积分和排名。
修正方案
假设你的模型结构如下(若和实际模型有差异,可对应调整关联字段):
# models.py from django.db import models class Tournament(models.Model): name = models.CharField(max_length=100) current_season = models.ForeignKey('Season', on_delete=models.SET_NULL, null=True, blank=True) class Season(models.Model): tournament = models.ForeignKey(Tournament, on_delete=models.CASCADE) year = models.CharField(max_length=4) class Team(models.Model): name = models.CharField(max_length=100) tournament = models.ForeignKey(Tournament, on_delete=models.CASCADE) class Match(models.Model): season = models.ForeignKey(Season, on_delete=models.CASCADE) home_team = models.ForeignKey(Team, on_delete=models.CASCADE, related_name='home_matches') away_team = models.ForeignKey(Team, on_delete=models.CASCADE, related_name='away_matches') kickoff_time = models.DateTimeField() class Goal(models.Model): match = models.ForeignKey(Match, on_delete=models.CASCADE, related_name='goals') team = models.ForeignKey(Team, on_delete=models.CASCADE) player = models.ForeignKey('Player', on_delete=models.CASCADE) minute = models.IntegerField()
修正后的统计逻辑(views.py)
from django.db.models import Count, Sum, Case, When, IntegerField, Q, F from django.http import JsonResponse from .models import Team, Season, Match def get_team_standings(request): season_id = request.GET.get('season_id') if not season_id: return JsonResponse({'error': 'Season ID is required'}, status=400) try: current_season = Season.objects.get(id=season_id) except Season.DoesNotExist: return JsonResponse({'error': 'Season not found'}, status=404) # 先统计当前赛季所有比赛的主客队进球数 season_matches = Match.objects.filter(season=current_season).annotate( home_goals=Count('goals', filter=Q(goals__team=F('home_team'))), away_goals=Count('goals', filter=Q(goals__team=F('away_team'))) ) # 统计球队的总进球、胜场、积分,并按排名规则排序 teams = Team.objects.filter(tournament=current_season.tournament).annotate( # 总进球数:该球队在当前赛季所有比赛中的进球总和 total_goals=Count('goals', filter=Q(goals__match__season=current_season)), # 胜场数:主场获胜+客场获胜的场次 wins=Sum( Case( # 主场获胜:主队进球数 > 客队进球数 When( home_matches__in=season_matches, home_matches__home_goals__gt=home_matches__away_goals, then=1 ), # 客场获胜:客队进球数 > 主队进球数 When( away_matches__in=season_matches, away_matches__away_goals__gt=away_matches__home_goals, then=1 ), default=0, output_field=IntegerField() ) ), # 积分计算:胜3分,平1分,负0分 points=Sum( Case( # 主场胜 When( home_matches__in=season_matches, home_matches__home_goals__gt=home_matches__away_goals, then=3 ), # 主场平 When( home_matches__in=season_matches, home_matches__home_goals=home_matches__away_goals, then=1 ), # 客场胜 When( away_matches__in=season_matches, away_matches__away_goals__gt=away_matches__home_goals, then=3 ), # 客场平 When( away_matches__in=season_matches, away_matches__away_goals=away_matches__home_goals, then=1 ), default=0, output_field=IntegerField() ) ) ).order_by('-points', '-total_goals') # 排名规则:积分优先,同分按总进球降序 # 整理返回的排名数据 standings = [] for rank, team in enumerate(teams, start=1): standings.append({ 'rank': rank, 'team_name': team.name, 'total_goals': team.total_goals or 0, 'wins': team.wins or 0, 'points': team.points or 0 }) return JsonResponse({'standings': standings})
关键调整说明
- 进球数计算:通过
Count函数结合filter,从Goal模型中统计每场比赛主客队的进球数,替代原来直接调用Match模型不存在的字段。 - 胜负判断:基于每场比赛的进球数对比,用
Case/When分别判断球队作为主/客队时的胜负情况。 - 排名规则:按积分降序排序,积分相同则按总进球数降序,可根据联赛规则调整为净胜球等其他指标。
内容的提问来源于stack exchange,提问作者Ahmed Wagdi
相关产品推荐
相关产品推荐

