Django 2.2.12中如何通过嵌套Regroup按RiskCategory分组展示RiskRating
按RiskCategory分组展示RiskRating的实现方案
嘿,这个需求其实很容易搞定!你已经找对了方向,用Django的regroup标签就可以实现,但有个关键细节得注意,不然分组结果可能不符合预期。我一步步给你讲:
第一步:视图里必须先排序!
Django的regroup标签是基于连续的相同值来分组的,如果你的riskratings没有按RiskCategory排序,同一个分类的RiskRating可能会被拆成多个组。所以在视图里要加上排序:
# 视图中的查询语句,按RiskCategory的name排序(也可以按主键id排序) riskratings = RiskRating.objects.all().order_by('risktype__riskcategory__name')
第二步:模板里的嵌套分组代码
你写的{% regroup riskratings by risktype.riskcategory as ratingsbycategory %}是正确的,接下来只需要遍历分组后的结果就行。如果需要更清晰的层级(分类→风险类型→风险评级),可以再嵌套一层regroup;如果不需要,直接遍历分类下的所有RiskRating也可以。
方案1:完整嵌套层级(分类→风险类型→评级)
{% regroup riskratings by risktype.riskcategory as category_groups %} {% for category_group in category_groups %} <h2>{{ category_group.grouper.name }}</h2> <!-- 显示分类名称 --> {# 再按RiskType分组 #} {% regroup category_group.list by risktype as type_groups %} {% for type_group in type_groups %} <h3>风险类型:{{ type_group.grouper.id }}</h3> <!-- 如果RiskType有name字段可以替换成.name --> <ul> {% for rating in type_group.list %} <li>风险评级ID:{{ rating.id }}</li> <!-- 显示RiskRating的字段,按需替换 --> {% endfor %} </ul> {% endfor %} {% empty %} <p>暂时没有任何风险评级数据</p> {% endfor %}
方案2:直接按分类展示所有评级
如果不需要按RiskType二次分组,简化版代码如下:
{% regroup riskratings by risktype.riskcategory as category_groups %} {% for category_group in category_groups %} <h2>{{ category_group.grouper.name }}</h2> <ul> {% for rating in category_group.list %} <li>所属风险类型:{{ rating.risktype.id }} | 评级ID:{{ rating.id }}</li> {% endfor %} </ul> {% empty %} <p>暂时没有任何风险评级数据</p> {% endfor %}
小优化:给模型加__str__方法
为了在模板里更友好地显示模型对象,建议给每个模型添加__str__方法,这样直接调用{{ category_group.grouper }}就能显示分类名称,不用写.name了:
class RiskCategory(models.Model): name = models.CharField(max_length=400, blank=True) def __str__(self): return self.name or f"分类ID: {self.id}" class RiskType(models.Model): riskcategory = models.ForeignKey(RiskCategory, on_delete=models.CASCADE, related_name="risksforcategory") def __str__(self): return f"{self.riskcategory} - 类型ID: {self.id}" class RiskRating(models.Model): risktype = models.ForeignKey(RiskType, on_delete=models.CASCADE, related_name="ratingsforrisk") def __str__(self): return f"{self.risktype} - 评级ID: {self.id}"
这样模板里的{{ category_group.grouper }}就会直接显示分类名称,看起来更简洁!
内容的提问来源于stack exchange,提问作者Paul Noon
相关产品推荐
相关产品推荐

