Django使用ForeignKey关联多模型时如何在模板获取匹配条目
问题分析
你当前的实现问题是game_status取了全量的Relation记录,没有和当前访问的Game实例做绑定过滤,所以无法筛选出和当前Game匹配的关联数据。
解决方案
方案1:修改视图上下文过滤逻辑
直接在get_context_data中过滤出和当前Game关联的Relation条目即可,修改后的视图代码如下:
class GameDetailView(DetailView): model = models.Game context_object_name = 'game_detail' template_name = 'gamesDB/game_detail.html' def get_context_data(self, **kwargs): context = super(GameDetailView, self).get_context_data(**kwargs) # 仅过滤和当前Game实例匹配的Relation条目 context.update({ 'game_status': models.Relation.objects.filter(game=self.object) }) return context
模板中使用方式:
<!-- 遍历当前游戏的所有关联分销商 --> {% for rel in game_status %} <p>分销商名称:{{ rel.distributor.dist }}</p> {% empty %} <p>暂无关联分销商</p> {% endfor %}
方案2:直接使用Django反向关联(无需修改视图)
Django会自动为外键字段生成反向关联属性,默认命名规则为关联模型名小写_set,这里Relation模型关联了Game,所以Game实例可以直接通过relation_set拿到所有关联的Relation条目,直接在模板中调用即可:
<!-- 不用修改视图代码,直接通过Game实例调用反向关联 --> {% for rel in game_detail.relation_set.all %} <p>分销商名称:{{ rel.distributor.dist }}</p> {% empty %} <p>暂无关联分销商</p> {% endfor %}
可选优化:如果想自定义反向关联的名称,可以修改Relation模型的game字段定义,添加related_name参数:
class Relation(models.Model): game = models.ForeignKey('Game', on_delete=models.CASCADE, related_name='relations') distributor = models.ForeignKey('Distributor', on_delete=models.CASCADE)
之后模板里就可以用game_detail.relations.all调用,可读性更好。
性能优化建议
如果需要同时加载关联的分销商数据,建议重写get_queryset方法使用预加载,大幅减少数据库查询次数:
class GameDetailView(DetailView): model = models.Game context_object_name = 'game_detail' template_name = 'gamesDB/game_detail.html' def get_queryset(self): # 预加载关联的Relation和Distributor数据,全程仅需2次SQL查询 return super().get_queryset().prefetch_related('relation_set__distributor')
内容的提问来源于stack exchange,提问作者Rafael Avant
相关产品推荐
相关产品推荐

