Django中exclude(id=id)的id获取及关联产品平均评分显示问题
问题解决步骤
1. 搞懂.exclude(id=id)的逻辑
这里两个id的含义不同:
- 第一个
id是Product模型的主键字段(Django默认生成的主键) - 第二个
id是当前详情页对应的产品ID,也就是你从URL路由里捕获的参数(比如视图函数def product_detail(request, id):里的id)
这条语句的作用是:筛选出和当前产品同分类的所有产品,但排除当前产品本身,避免关联产品列表里出现自己。
2. 修复当前产品的评分展示问题
先检查views.py的产品详情视图,确保已计算当前产品的平均评分并传入模板:
from django.db.models import Avg def product_detail(request, id): product = Product.objects.get(id=id) # 计算当前产品平均评分,处理无评论的情况 avg_reviews = ProductReview.objects.filter(product=product).aggregate(avg_rating=Avg('review_rating')) # 无评论时给默认值0,避免模板显示None avg_reviews['avg_rating'] = avg_reviews['avg_rating'] or 0 # 关联产品查询保留原有逻辑 related_products = Product.objects.filter(category=product.category).exclude(id=id) # 把计算好的评分传入模板上下文 context = { 'product': product, 'avg_reviews': avg_reviews, 'related_products': related_products, } return render(request, 'product-detail.html', context)
然后修改模板product-detail.html,优化评分显示格式:
<span class="avg-rating">{{ avg_reviews.avg_rating|floatformat:1 }}</span>/5
如果之前视图没把avg_reviews传入上下文,模板自然拿不到值,这是最常见的问题。
3. 实现关联产品的平均评分展示
不要循环每个关联产品单独计算评分(会产生N+1查询,效率极低),直接用annotate在数据库层面批量计算:
修改views.py里的关联产品查询:
from django.db.models import Avg, Case, When, Value, FloatField related_products = Product.objects.filter(category=product.category).exclude(id=id).annotate( avg_rating=Case( # 有评论的产品计算平均分,无评论返回0 When(productreview__isnull=False, then=Avg('productreview__review_rating')), default=Value(0.0), output_field=FloatField() ) )
之后在模板里遍历关联产品时,直接调用自带的avg_rating属性:
{% for item in related_products %} <div class="related-product-item"> <h4>{{ item.name }}</h4> <span class="avg-rating">{{ item.avg_rating|floatformat:1 }}</span>/5 </div> {% endfor %}
补充:检查模型关联正确性
确保ProductReview的外键关联配置正确:
# models.py class ProductReview(models.Model): product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name='productreview') review_rating = models.IntegerField(choices=[(1,1),(2,2),(3,3),(4,4),(5,5)]) # 其他字段...
如果没设置related_name,默认是productreview_set,那annotate里要改成Avg('productreview_set__review_rating')。
内容的提问来源于stack exchange,提问作者Artem
相关产品推荐
相关产品推荐

