Django单商品平均评分渲染异常:显示所有商品而非指定商品
问题描述
尝试展示单个指定商品的用户平均评分,当前代码会渲染所有商品及其关联评分,而非仅目标商品。页面还需同时展示:
- 单商品的平均评分(待修复)
- 指定商品的所有用户评论(功能正常)
疑问:是否是评论功能导致的问题?是否需要在视图中关联product_id?如何修改?
相关代码
Models
class Product(models.Model): name = models.CharField('Product Name', max_length=120, null=True) class Meta: db_table='Product' def __str__(self): return str(self.name) class ReviewRating(models.Model): user = models.ForeignKey(User,blank=True,on_delete=models.CASCADE) product=models.ForeignKey(Product,related_name="comments", on_delete=models.CASCADE) rating_1 = models.IntegerField(choices=RATING1,default=0) def __str__(self): return '%s - %s - %s'%(self.user, self.product, self.date_added)
Views
from django.db.models import Avg def Notes (request, product_id): product = Product.objects.get(pk=product_id) data = Product.objects.order_by('name').annotate( avg_rating_1 =Avg('comments__rating_1 '), return render(request, 'main/notes.html',{'product':product, 'data':data})
Template
{% for ReviewRating in data%} {{ReviewRating.avg_rating_1 }} {% endfor %}
问题原因及解决方案
问题原因
和评论功能无关,核心问题是视图中data = Product.objects.order_by('name').annotate(...)查询的是所有商品,并给每个商品加上平均评分,所以模板循环时会渲染所有商品的评分,而非仅目标商品。
修改方案
1. 优化视图代码(两种可选方式)
方式一:直接通过已获取的product对象计算平均评分
不需要额外查询所有商品,直接对当前商品的评论集求平均值:
from django.db.models import Avg def Notes(request, product_id): product = Product.objects.get(pk=product_id) # 计算当前商品的平均评分,无评分时默认显示0 avg_rating = product.comments.aggregate(avg_rating_1=Avg('rating_1'))['avg_rating_1'] or 0 # 获取当前商品的所有评论(保留原有正常评论功能) comments = product.comments.all() return render(request, 'main/notes.html', { 'product': product, 'avg_rating': avg_rating, 'comments': comments })
方式二:过滤Product查询集到当前商品
如果坚持用annotate的方式,需要添加过滤条件限定到当前product_id:
from django.db.models import Avg def Notes(request, product_id): product = Product.objects.get(pk=product_id) # 仅查询当前商品并标注平均评分 data = Product.objects.filter(pk=product_id).annotate( avg_rating_1 = Avg('comments__rating_1') ).first() return render(request, 'main/notes.html', {'product': product, 'data': data})
2. 修改模板代码
因为只需要单个商品的评分,不需要循环遍历:
- 对应方式一的模板:
<!-- 展示单个商品的平均评分 --> <p>平均评分:{{ avg_rating }}</p> <!-- 展示该商品的所有评论(保留原有正常逻辑) --> {% for comment in comments %} <p>{{ comment.user }}:{{ comment.rating_1 }}分</p> {% endfor %}
- 对应方式二的模板:
<!-- 展示单个商品的平均评分 --> <p>平均评分:{{ data.avg_rating_1 }}</p> <!-- 评论部分保留原有正常逻辑 -->
内容的提问来源于stack exchange,提问作者PhilM
相关产品推荐
相关产品推荐

