Django项目中'QuerySet'无'Breakdown'属性错误的解决方法
解决指定Workout下Exercise的Breakdown数据展示问题
先明确模型关联逻辑(参考示例)
假设你的模型结构如下(如果实际结构不同,对应调整关联字段和反向名称):
class Workout(models.Model): name = models.CharField(max_length=100) # 其他训练相关字段 class Exercise(models.Model): workout = models.ForeignKey(Workout, on_delete=models.CASCADE, related_name='exercises') name = models.CharField(max_length=100) # 其他动作相关字段 class Breakdown(models.Model): exercise = models.ForeignKey(Exercise, on_delete=models.CASCADE, related_name='breakdowns') repetitions = models.IntegerField() order = models.IntegerField() # 其他组次相关字段
错误原因分析
你执行breakdowns=excercises.Breakdown.repetitions.all()报错,是因为excercises(注意还有拼写错误,正确是exercises)是QuerySet对象(多个Exercise实例的集合),而非单个Exercise对象,无法直接通过它访问Breakdown关联模型。
正确实现方案
方案1:预加载关联数据(高效推荐)
用prefetch_related一次性拉取所有关联数据,避免多次数据库查询,同时指定Breakdown按order排序:
from django.db.models import Prefetch def workout_details(request, workout_id): # 获取指定Workout,同时预加载关联的Exercise和对应的Breakdown workout = Workout.objects.prefetch_related( Prefetch( 'exercises__breakdowns', queryset=Breakdown.objects.order_by('order'), to_attr='sorted_breakdowns' ) ).get(id=workout_id) return render(request, 'workout_details.html', {'workout': workout})
模板中遍历展示:
<h1>{{ workout.name }} 训练详情</h1> {% for exercise in workout.exercises %} <h3>{{ exercise.name }}</h3> <ul> {% for breakdown in exercise.sorted_breakdowns %} <li>第{{ breakdown.order }}组: {{ breakdown.repetitions }}次</li> {% endfor %} </ul> {% endfor %}
方案2:逐个遍历Exercise获取Breakdown
如果不需要预加载,可直接遍历每个Exercise实例获取对应的Breakdown:
def workout_details(request, workout_id): workout = Workout.objects.get(id=workout_id) # 整理每个动作及其对应的组次数据 exercise_data = [] for exercise in workout.exercises.all(): # 获取当前动作的所有组次,按order排序 breakdowns = exercise.breakdowns.all().order_by('order') exercise_data.append({ 'exercise': exercise, 'breakdowns': breakdowns }) return render(request, 'workout_details.html', {'exercise_data': exercise_data})
模板中遍历展示:
<h1>训练详情</h1> {% for item in exercise_data %} <h3>{{ item.exercise.name }}</h3> <ul> {% for breakdown in item.breakdowns %} <li>顺序{{ breakdown.order }}: {{ breakdown.repetitions }}次</li> {% endfor %} </ul> {% endfor %}
注意事项
- 拼写检查:确保代码中是
exercises而非excercises,避免不必要的错误。 - 反向关联名称:如果
Exercise模型的ForeignKey未设置related_name,默认反向关联名为exercise_set,需将代码中的workout.exercises.all()改为workout.exercise_set.all()。 - 数据校验:确认数据库中存在指定Workout关联的Exercise和Breakdown记录,避免无结果的情况。
内容的提问来源于stack exchange,提问作者A_K
相关产品推荐
相关产品推荐

