Django多对多模型关联示例:健身APP模型设计与数据操作
健身APP:Exercise与MuscleGroup多对多关联实现方案
一、模型类编写(以Django ORM为例)
针对需求,我们需要给MuscleGroup定义基础信息,给Exercise区分主要目标肌群和次要目标肌群两个多对多关联,通过related_name实现清晰的反向查询逻辑:
from django.db import models class MuscleGroup(models.Model): name = models.CharField(max_length=50, unique=True, verbose_name="肌群名称") def __str__(self): return self.name class Exercise(models.Model): name = models.CharField(max_length=100, unique=True, verbose_name="动作名称") primary_muscles = models.ManyToManyField( MuscleGroup, related_name="primary_exercises", verbose_name="主要目标肌群", help_text="该动作主要刺激的肌群" ) secondary_muscles = models.ManyToManyField( MuscleGroup, related_name="secondary_exercises", blank=True, verbose_name="次要目标肌群", help_text="该动作辅助刺激的肌群" ) def __str__(self): return self.name
说明:
- 两个
ManyToManyField分别绑定主次肌群,避免混在一起难以区分 related_name让反向查询更直观:比如通过肌群可以直接获取「以它为主要目标的动作」或「以它为次要目标的动作」
二、数据库填充脚本
方式1:Django Shell临时填充
在项目根目录执行python manage.py shell,然后运行以下代码:
from your_app_name.models import MuscleGroup, Exercise # 批量创建肌群 muscle_data = ["胸肌", "背阔肌", "肱三头肌", "肱二头肌", "肩部", "股四头肌", "臀大肌", "核心肌群"] muscle_groups = {name: MuscleGroup.objects.create(name=name) for name in muscle_data} # 创建动作并关联肌群 bench_press = Exercise.objects.create(name="杠铃卧推") bench_press.primary_muscles.add(muscle_groups["胸肌"]) bench_press.secondary_muscles.add(muscle_groups["肱三头肌"], muscle_groups["肩部"]) pull_up = Exercise.objects.create(name="引体向上") pull_up.primary_muscles.add(muscle_groups["背阔肌"]) pull_up.secondary_muscles.add(muscle_groups["肱二头肌"], muscle_groups["肩部"]) lunge = Exercise.objects.create(name="箭步蹲") lunge.primary_muscles.add(muscle_groups["股四头肌"], muscle_groups["臀大肌"]) lunge.secondary_muscles.add(muscle_groups["核心肌群"])
方式2:可复用的管理命令
在APP目录下创建management/commands/populate_fitness_data.py,编写可重复执行的填充脚本:
from django.core.management.base import BaseCommand from your_app_name.models import MuscleGroup, Exercise class Command(BaseCommand): help = "批量填充健身动作与肌群数据" def handle(self, *args, **options): # 开发环境可清空旧数据(生产环境注释) MuscleGroup.objects.all().delete() Exercise.objects.all().delete() # 创建肌群 muscle_list = ["胸肌", "背阔肌", "肱三头肌", "肱二头肌", "肩部", "股四头肌", "臀大肌", "核心肌群"] muscle_map = {name: MuscleGroup.objects.create(name=name) for name in muscle_list} # 定义动作数据 exercise_list = [ { "name": "杠铃卧推", "primary": ["胸肌"], "secondary": ["肱三头肌", "肩部"] }, { "name": "引体向上", "primary": ["背阔肌"], "secondary": ["肱二头肌", "肩部"] }, { "name": "箭步蹲", "primary": ["股四头肌", "臀大肌"], "secondary": ["核心肌群"] }, { "name": "哑铃肩推", "primary": ["肩部"], "secondary": ["肱三头肌", "核心肌群"] } ] # 批量创建动作并关联肌群 for ex_data in exercise_list: exercise = Exercise.objects.create(name=ex_data["name"]) exercise.primary_muscles.add(*[muscle_map[name] for name in ex_data["primary"]]) exercise.secondary_muscles.add(*[muscle_map[name] for name in ex_data["secondary"]]) self.stdout.write(self.style.SUCCESS("健身数据填充完成!"))
执行命令即可完成填充:
python manage.py populate_fitness_data
三、字段访问测试代码
通过以下代码验证正向/反向查询是否正常:
from your_app_name.models import Exercise, MuscleGroup # 正向查询:通过动作获取主次肌群 bench_press = Exercise.objects.get(name="杠铃卧推") print(f"动作名称:{bench_press.name}") print(f"主要肌群:{', '.join(mg.name for mg in bench_press.primary_muscles.all())}") print(f"次要肌群:{', '.join(mg.name for mg in bench_press.secondary_muscles.all())}") # 反向查询:通过肌群获取关联动作 chest = MuscleGroup.objects.get(name="胸肌") print(f"\n以胸肌为主要目标的动作:{', '.join(ex.name for ex in chest.primary_exercises.all())}") shoulders = MuscleGroup.objects.get(name="肩部") print(f"以肩部为次要目标的动作:{', '.join(ex.name for ex in shoulders.secondary_exercises.all())}") # 多条件查询:筛选包含指定肌群的动作 from django.db.models import Q target_exercises = Exercise.objects.filter( Q(primary_muscles__name="核心肌群") | Q(secondary_muscles__name="核心肌群") ).distinct() print(f"\n涉及核心肌群的动作:{', '.join(ex.name for ex in target_exercises)}")
运行后会输出清晰的关联数据,验证多对多关系的正确性。
内容的提问来源于stack exchange,提问作者BLimitless
相关产品推荐
相关产品推荐

