学习Django的教程。在页面上“产品”是显示评级为这个产品。也有相关产品,我不能理解的逻辑来显示每个相关产品的评级。
product-detail.html
{% extends 'base.html' %}
{% load static %}
{% block content %}
<main class="container my-4">
<h3 class="my-4 border-bottom pb-1">{{data.title}}</h3>
<div class="row">
<!-- Images -->
<div class="col-md-4">
<img id="zoom_01" data-zoom-image="/media/{{data.image}}" src="/media/{{data.image}}" class="card-img-top" alt="{{data.title}}">
</div>
<div class="col-md-8">
<p>{{data.detail}}</p>
<hr/>
<table class="table table-bordered">
<tr>
<h6>Цена</h6>
<h6>₽ <span class="product-price-{{data.id}}">{{data.price}}</span></h6>
</tr>
</table>
<hr/>
<div class="input-group my-3" style="width:30%;">
<input type="number" value="1" class="form-control product-qty-{{data.id}}" id="productQty" />
<div class="input-group-append">
<input type="hidden" class="product-id-{{data.id}}" value="{{data.id}}" />
<input type="hidden" class="product-title-{{data.id}}" value="{{data.title}}" />
<input type="hidden" class="product-image-{{data.id}}" value="{{data.image}}" />
<button class="btn btn-primary btn-sm add-to-cart" data-index="{{data.id}}" type="button" id="addToCartBtn"><i class="fa fa-shopping-cart"></i> В корзину</button>
</div>
</div>
</div>
</div>
<hr />
.....
<!-- Reviews -->
<div class="col-md-6">
<h3 class="my-3">Reviews - <span class="avg-rating">{{avg_reviews.avg_rating}}</span>/5 <i class="fa fa-star text-warning"></i>
{% if user.is_authenticated %}
{% if canAdd %}
<button type="button" data-toggle="modal" data-target="#productReview" class="btn btn-warning bt-sm float-right reviewBtn">Add review</button>
{% endif %}
{% endif %}
</h3>
<div class="card">
<div class="card-body review-list" style="max-height: 400px; overflow; auto;">
<!-- Detail -->
{% if reviews %}
{% for review in reviews %}
<blockquote class="blockquote text-right">
<small>{{review.review_text}}</small>
<footer class="blockquote-footer">{{review.user}}
<cite title="Source Title">
{% for star in review.review_rating|ljust:review.review_rating %}
<i class="fa fa-star text-warning"></i>
{% endfor %}
</cite>
</footer>
</blockquote>
<hr />
{% endfor %}
{% else %}
<p class="no-data">Add first review</p>
{% endif %}
</div>
</div>
</div>
.....
<!-- Related Products -->
<h3 class="mt-4 mb-3 border-bottom pb-1">Related Products</h3>
<div class="row">
{% for product in related %}
<div class="col-lg-3 col-sm-4 mb-4">
<div class="card shadow">
<a href="/product/{{product.id}}"><img src="/media/{{product.image}}" class="card-img-top" alt="{{product.title}}"></a>
<div class="card-body">
<h6 class="card-text"><a href="/product/{{product.id}}">{{product.title}}</a></h6>
</div>
<div class="card-footer">
<button class="btn btn-sm btn-primary"><i class="fa fa-shopping-cart"></i></button>
<button class="btn btn-sm btn-danger"><i class="fa fa-heart"></i></button>
<span class="float-right">
4.5/5
<i class="fa fa-star text-warning"></i>
</span>
</div>
</div>
</div>
{% endfor %}
</div>
</main>
{% endblock %}
models.py
class Product(models.Model):
title = models.CharField(max_length=30, null=True)
detail = models.TextField(max_length=400, null=True)
category = models.ForeignKey(Category, on_delete=models.CASCADE, null=True, blank=False)
image = models.ImageField(upload_to="prod_imgs/", null=True)
price = models.DecimalField(max_digits=7, decimal_places=2, null=True)
status = models.BooleanField(default=True)
is_featured = models.BooleanField(default=False)
class Meta:
verbose_name_plural = '02.Products'
def image_tag(self):
return mark_safe('<img src="%s" width="50" height="50" />' % (self.image.url))
def __str__(self):
return self.title
RATING=(
(1,'1'),
(2,'2'),
(3,'3'),
(4,'4'),
(5,'5'),
)
class ProductReview(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
product = models.ForeignKey(Product, on_delete=models.CASCADE)
review_text = models.TextField()
review_rating = models.IntegerField(choices=RATING)
class Meta:
verbose_name_plural = '07. ProductReviews'
def get_review_rating(self):
return self.review_rating
views.py
def product_detail(request, id):
product = Product.objects.get(id=id)
related_products = Product.objects.filter(category=product.category).exclude(id=id)[:4]
reviewForm = ReviewAdd()
canAdd = True
if request.user.is_authenticated:
reviewCheck = ProductReview.objects.filter(user=request.user, product=product).count()
if reviewCheck > 0:
canAdd = False
reviews = ProductReview.objects.filter(product=product)
avg_reviews = ProductReview.objects.filter(product=product).aggregate(avg_rating=Avg('review_rating'))
return render(request, 'product_detail.html', {'data': product, 'related': related_products, 'form': reviewForm, 'canAdd': canAdd, 'reviews': reviews, 'avg_reviews': avg_reviews})
def save_review(request, pid):
product = Product.objects.get(pk=pid)
user = request.user
review = ProductReview.objects.create(
user=user,
product=product,
review_text=request.POST['review_text'],
review_rating=request.POST['review_rating'],
)
data = {
'user': user.username,
'review_text': request.POST['review_text'],
'review_rating': request.POST['review_rating'],
}
avg_reviews = ProductReview.objects.filter(product=product).aggregate(avg_rating=Avg('review_rating'))
return JsonResponse({'bool': True, 'data': data, 'avg_reviews': avg_reviews})
<span class="avg-rating">{{avg_reviews.avg_rating}}</span>/5
在这里不起作用。我知道对于相关产品,我只能从related_products = Product.objects.filter(category=product.category).exclude(id=id)
,例如related_avg_reviews = ProductReview.objects.filter(product=related_product).aggregate(avg_rating=Avg('review_rating'))
但我不知道该怎么做。
1条答案
按热度按时间eqqqjvef1#
我没有看到你的模型,但是你需要把avg rating注解到你的related_products查询集。聚合为所有行生成avg。我认为它应该看起来像:
这里我们使用反向的键关系将avg_rating注解到Product对象。在related_products的forloop中的模板中,您可以引用