如何使用Django模板语法计算单个训练动作的总容量?
在Django模板中计算单个训练动作的总容量
问题背景
已实现训练组(ExerciseSetModel)的单组容量计算(setvolume方法),需要在Django模板中计算单个训练动作(ExerciseModel)下所有训练组的容量总和。
现有代码
模型代码
class ExerciseModel(models.Post): exercisename = models.TextField(max_length=500, verbose_name='text', blank=True, null=True, default="text") class ExerciseSetModel(models.Post): exercise = models.ForeignKey(ExerciseModel, on_delete=models.CASCADE, default=None,) repsnumber = models.IntegerField(default=1, null=True, blank=True) weightnumber = models.IntegerField(default=1, null=True, blank=True) def setvolume(self): return self.repsnumber * self.weightnumber
视图代码
@login_required def homeview(request): exercises = ExerciseModel.objects.all() context = { 'exercises': exercises, } return TemplateResponse(request, 'poststemplates/posthome.html', context)
模板代码
{% for exercise in exercises %} {% for set in exercise.exercisesetmodel_set.all %} {{set.setvolume}} {% endfor %} {% endfor %}
解决方案
推荐方案:在模型中添加总容量计算方法
将总容量的计算逻辑封装到模型中,既符合MVC设计思想,又能配合预取关联数据提升性能。
- 修改
ExerciseModel,添加exercise_volume方法:
class ExerciseModel(models.Post): exercisename = models.TextField(max_length=500, verbose_name='text', blank=True, null=True, default="text") def exercise_volume(self): # 累加当前训练动作下所有训练组的单组容量 return sum(set_item.setvolume() for set_item in self.exercisesetmodel_set.all())
- 优化视图,预取关联训练组数据(避免N+1查询问题):
@login_required def homeview(request): exercises = ExerciseModel.objects.all().prefetch_related('exercisesetmodel_set') context = { 'exercises': exercises, } return TemplateResponse(request, 'poststemplates/posthome.html', context)
- 模板中直接调用总容量方法:
{% for exercise in exercises %} <h3>{{ exercise.exercisename }}</h3> <p>总容量: {{ exercise.exercise_volume }}</p> <p>各训练组容量:</p> {% for set in exercise.exercisesetmodel_set.all %} <span>{{ set.setvolume }}</span> {% endfor %} {% endfor %}
备选方案:自定义模板过滤器(仅适用于无法修改模型的场景)
如果无法修改模型代码,可自定义求和过滤器实现:
- 在应用目录下创建
templatetags文件夹,新增exercise_tags.py文件:
from django import template register = template.Library() @register.filter def sum_volumes(sets): return sum(set_item.setvolume() for set_item in sets)
- 模板中加载并使用过滤器:
{% load exercise_tags %} {% for exercise in exercises %} <h3>{{ exercise.exercisename }}</h3> <p>总容量: {{ exercise.exercisesetmodel_set.all|sum_volumes }}</p> {% for set in exercise.exercisesetmodel_set.all %} <span>{{ set.setvolume }}</span> {% endfor %} {% endfor %}
内容的提问来源于stack exchange,提问作者Vinko Oakniiv
相关产品推荐
相关产品推荐

