Django 如何查询特定用户各锻炼动作的最大举重重量
实现每个用户对应锻炼动作的最大重量查询
要实现该需求核心使用Django ORM的annotate做分组聚合,和用于全局单值统计的aggregate不同,annotate会按照指定的维度做分组,给每个分组计算对应的聚合值,完全匹配“按锻炼动作分类,取每个分类下用户的最高重量”的场景。
具体查询实现
- 先理清模型关联链路:
Profile通过一对一关联绑定登录用户Workout外键关联对应用户的Profile、关联具体的Exercise动作
- 视图层查询代码示例:
# 先导入需要的聚合方法 from django.db.models import Max @login_required def get_user_exercise_max_weight(request): # 锁定当前登录用户的Profile,确保只查询私有数据 current_user_profile = request.user.profile # 核心查询逻辑 exercise_max_list = Workout.objects.filter( # 过滤条件:只取当前用户的训练记录 user=current_user_profile ).values( # 明确分组维度:按锻炼动作的ID、名称做分组 'exercise__id', 'exercise__name' ).annotate( # 给每个分组计算最大重量,自定义字段名方便后续模板调用 personal_max_weight=Max('weight') ) return render(request, 'personal_max.html', { 'max_weight_list': exercise_max_list })
模板层渲染示例
{% for record in max_weight_list %} <div class="max-weight-card"> <h4>{{ record.exercise__name }}</h4> <p>个人最佳重量:{{ record.personal_max_weight }} kg</p> </div> {% endfor %}
常见踩坑提醒
- 不要直接在全量
Workout数据集上做聚合:如果漏掉filter(user=current_user_profile)的条件,会把所有用户的训练数据纳入计算,违反数据私有性要求 - 不要漏掉
values('exercise__id', 'exercise__name')的分组声明:如果没有指定分组维度,Django会默认把每条Workout记录的主键作为分组依据,最终所有聚合结果和原始记录没有区别 - 不要混淆
aggregate和annotate的适用场景:aggregate是对整个查询集计算单个全局统计值(比如全局所有用户的最高卧推重量),annotate才是按维度拆分的分组统计,和当前需求匹配
附带模型优化提示:当前
Exercise模型没有关联用户外键,若要实现“锻炼动作也为用户私有”的规则,需要给Exercise增加user = models.ForeignKey(Profile, on_delete=models.CASCADE)字段,创建动作时自动绑定当前用户即可,该改动不影响现有最大重量查询逻辑。
内容的提问来源于stack exchange,提问作者sgt_pepper85
相关产品推荐
相关产品推荐

