Django如何通过反向关联获取指定备件存在评价的车型及品牌
实现方案
1. 视图层查询逻辑
你可以直接用Django ORM的跨关联查询语法实现需求,核心是利用Review模型的外键反向关联关系,代码如下:
def get_spare_part(request, spare_part_id): spare_part = get_object_or_404(SparePart, pk=spare_part_id) # 查询所有和当前备件有关联评价的车型实例,distinct去重 installed_models = CarModel.objects.filter(review__spare_part=spare_part).distinct() # 批量查询关联的品牌,构造id到品牌实例的映射,避免N+1查询 brand_ids = installed_models.values_list('brand_id', flat=True) brand_map = {brand.pk: brand for brand in CarBrand.objects.filter(pk__in=brand_ids)} # 打包品牌和车型数据传给模板 installed_on_cars = [ {"model": model, "brand": brand_map.get(model.brand_id)} for model in installed_models ] context = { 'spare_part': spare_part, 'installed_on_cars': installed_on_cars, } return render(request, 'mileage/spare_part.html', context)
原理说明:Django会为每个外键字段自动生成反向查询关系,这里通过review__spare_part的双下划线跨关联语法,筛选出所有关联了当前备件评价的车型实例,distinct方法用来避免同一个车型有多条评价时重复返回结果。
2. 模板层渲染超链接
在spare_part.html中直接调用模型定义的get_absolute_url方法生成链接即可:
{% for item in installed_on_cars %} <div class="car-item"> <a href="{{ item.brand.get_absolute_url }}">{{ item.brand.brand }}</a> <span>-</span> <a href="{{ item.model.get_absolute_url }}">{{ item.model.model_name }}</a> </div> {% empty %} <p>暂无该备件的装车评价记录</p> {% endfor %}
可选优化方案
建议将CarModel中的brand_id字段改为外键关联CarBrand,可以简化查询逻辑,不需要手动构造品牌映射:
# 修改后的CarModel定义,db_column保持原有字段名,无需修改数据库 class CarModel(models.Model): model_name = models.CharField(max_length=60, db_index=True, verbose_name="Модель") brand = models.ForeignKey(CarBrand, on_delete=models.PROTECT, verbose_name="所属品牌", db_column='brand_id') def __str__(self): return self.model_name def get_absolute_url(self): return reverse_lazy('model_info', kwargs={'model_id': self.pk})
修改后视图层的查询可以简化为:
installed_on_cars = CarModel.objects.filter(review__spare_part=spare_part).distinct().select_related('brand')
模板层直接取值即可:
{% for model in installed_on_cars %} <div> <a href="{{ model.brand.get_absolute_url }}">{{ model.brand.brand }}</a> <span>-</span> <a href="{{ model.get_absolute_url }}">{{ model.model_name }}</a> </div> {% endfor %}
内容的提问来源于stack exchange,提问作者Vitalii Mytenko
相关产品推荐
相关产品推荐

