健身进度应用Django模型选型咨询:两种方案优劣势对比
针对健身进度追踪应用的Django模型选择
结论:当前需求下,第一种简洁版本更合适
你的需求只是记录每个动作的重量和次数,第一种模型完全匹配这个核心需求,而第二种的额外结构属于过度设计,反而会增加开发和维护成本。
第一种简洁版本分析
class Exercise(models.Model): name = models.CharField(max_length = 30) def __str__(self): return self.name class Set(models.Model): exercise = models.ForeignKey(Exercise, on_delete=models.CASCADE, related_name='sets') weight = models.FloatField(validators=[MinValueValidator(0)]) repetitions = models.IntegerField(validators=[MinValueValidator(1)]) def __str__(self): return self.exercise.name + ' set #' + str(self.pk)
- 优势:
- 结构极简,直接对应“动作→每组重量/次数”的逻辑,无冗余表
- 开发、查询、维护成本低:比如获取某个动作的所有训练记录,直接用
exercise.sets.all()即可,无需额外关联 - 数据一致性高:每组的归属、重量、次数直接绑定,不会出现逻辑冲突
- 适用场景:
- 仅需记录单组训练的基础数据(动作、重量、次数)
- 无后续扩展复杂训练计划、组模板、批量管理的需求
- 小型学习项目,优先保证简单易实现
第二种复杂版本分析
class Exercise(models.Model): # Attributes name = models.CharField(null=False, blank=False, max_length=100) # Methods def __str__(self): return self.name class ExerciseSet(models.Model): # Attributes for exercise sets exercise = models.ForeignKey(Exercise, null=False, blank=False, on_delete=models.CASCADE) sets = models.ManyToManyField("my_gym.Set", related_name="sets") number_of_sets = models.IntegerField(null=False, blank=False, default=3) # Methods def __str__(self): return str(self.exercise.name) + " - " + str(self.number_of_sets) + " sets" class Set(models.Model): # Attributes reps = models.PositiveIntegerField(null=False, blank=False, default=0) weight = models.DecimalField(max_digits=5, decimal_places=2) # Methods def __str__(self): return ( str(self.reps) + " " + " x " + str(self.weight) + " " )
- 劣势(针对当前需求):
- 多了一层
ExerciseSet中间表,属于冗余设计——当前需求不需要把多个Set打包成集合管理 - 存在数据一致性风险:
number_of_sets字段和实际关联的Set数量可能不一致,需要额外写逻辑校验 - 查询复杂度提升:获取某个动作的训练记录,需要先查
ExerciseSet再关联Set,多了一步关联操作
- 多了一层
- 优势(扩展场景):
- 支持复杂训练计划管理:比如把重复的
Set(如3组8次80kg)打包成模板复用 - 方便统计“一次训练中某个动作的总组数”,或批量修改一组
Set的归属
- 支持复杂训练计划管理:比如把重复的
- 适用场景:
- 需要实现训练计划模板功能(保存常用动作组配置)
- 要记录“某次训练中完成的一整套动作组”并做整体管理
- 后续计划扩展复杂健身追踪功能(如周期训练、组间休息、训练日志关联等)
内容的提问来源于stack exchange,提问作者A_K
相关产品推荐
相关产品推荐

