You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

请求协助优化Django/SQLite3梦幻橄榄球赛事模型架构

Django梦幻橄榄球锦标赛模型优化方案

核心问题拆解

  1. 队伍与分数绑定:原Game用ManyToManyField无法直接关联单支队伍的分数,需要明确每场比赛的对阵双方及各自得分。
  2. 层级逻辑梳理:年份代表一届完整锦标赛,轮次属于当届锦标赛,比赛属于对应轮次,拆分后结构更清晰,避免重复字段。

优化后模型设计

from django.db import models
from django.core.validators import MinValueValidator, MaxValueValidator, RegexValidator

class Owner(models.Model):
    name = models.CharField(max_length=200)
    email = models.EmailField(max_length=100)
    phone = models.CharField(max_length=12, null=True)

    def __str__(self):
        return self.name

class Team(models.Model):
    owner = models.ForeignKey(Owner, on_delete=models.CASCADE)
    name = models.CharField(max_length=200)

    def __str__(self):
        return self.name

class Tournament(models.Model):
    # 代表每一年的Toilet Bowl锦标赛
    year = models.SmallIntegerField(
        unique=True,
        validators=[
            MinValueValidator(2010),
            MaxValueValidator(2999),
            RegexValidator("^(20)([1-5][0-9])$")
        ]
    )
    # 绑定当届参赛队伍,确保每年固定6支
    participating_teams = models.ManyToManyField(Team)

    def __str__(self):
        return f"Toilet Bowl {self.year}"

class Round(models.Model):
    # 代表某届锦标赛中的一轮赛事
    tournament = models.ForeignKey(Tournament, on_delete=models.CASCADE)
    round_number = models.SmallIntegerField(validators=[MinValueValidator(1), MaxValueValidator(3)])

    class Meta:
        # 确保同一届锦标赛中轮次不重复
        unique_together = ('tournament', 'round_number')

    def __str__(self):
        return f"{self.tournament} - 第{self.round_number}轮"

class Game(models.Model):
    # 代表某一轮中的一场具体比赛
    round = models.ForeignKey(Round, on_delete=models.CASCADE)
    team1 = models.ForeignKey(Team, on_delete=models.CASCADE, related_name='team1_games')
    team1_score = models.IntegerField(default=0)
    team2 = models.ForeignKey(Team, on_delete=models.CASCADE, related_name='team2_games')
    team2_score = models.IntegerField(default=0)

    def __str__(self):
        return f"{self.round}: {self.team1} vs {self.team2}"

关键设计说明

  • Tournament模型:将年份抽象为独立的锦标赛实体,通过participating_teams关联当届6支参赛队伍,可通过表单或信号限制队伍数量为6,保证数据完整性。
  • Round模型:绑定到具体锦标赛,明确轮次归属,避免不同年份的轮次混淆。
  • Game模型:用两个独立的ForeignKey关联对阵队伍,直接绑定各自分数,完美解决原ManyToManyField无法关联分数的问题;related_name方便反向查询某支队伍参与的所有比赛。

额外建议

  • 若需要记录比赛胜负结果,可在Game中添加动态计算的属性,无需额外存储:
    @property
    def winner(self):
        if self.team1_score > self.team2_score:
            return self.team1
        elif self.team2_score > self.team1_score:
            return self.team2
        return None
    
  • 单字段的Year模型完全没必要,Tournament本身已经承担了按年区分赛事的作用,符合Django模型“一个模型对应一个业务实体”的设计原则。

内容的提问来源于stack exchange,提问作者Shawn Johnson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 09:50:43