通过评分高低的低高点来对产品进行排序
我正在尝试设置,以便可以通过高低和低高的评级来对我的产品进行排序,并显示在其背后的无等级。我似乎无法弄清楚,因此任何帮助都将不胜感激。我添加了代码ITHINK,如果您需要其他任何内容,我会添加它。 提前致谢。
我想要在高低排序时,它的评论首先具有最高的评分,如果它有点任何评分都以任何评分为后面的遥远。
我希望它的额定值最低,然后在评分后的最后一个额定评分。
views.py
from django.shortcuts import render, redirect, reverse, get_object_or_404
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.db.models import Q
from django.db.models.functions import Lower
from .models import Product, Category, Review
from .forms import ProductForm, ReviewForm
# Create your views here.
def all_products(request):
""" A view to show all products, including sorting and search queries """
products = Product.objects.all()
query = None
categories = None
sort = None
direction = None
if request.GET:
if 'sort' in request.GET:
sortkey = request.GET['sort']
sort = sortkey
if sortkey == 'name':
sortkey = 'lower_name'
products = products.annotate(lower_name=Lower('name'))
if sortkey == 'category':
sortkey = 'category__name'
if 'direction' in request.GET:
direction = request.GET['direction']
if direction == 'desc':
sortkey = f'-{sortkey}'
products = products.order_by(sortkey)
if 'category' in request.GET:
categories = request.GET['category'].split(',')
products = products.filter(category__name__in=categories)
categories = Category.objects.filter(name__in=categories)
if 'q' in request.GET:
query = request.GET['q']
if not query:
messages.error(request, "You didn't enter any search criteria!")
return redirect(reverse('products'))
queries = Q(name__icontains=query) | Q(description__icontains=query)
products = products.filter(queries)
current_sorting = f'{sort}_{direction}'
context = {
'products': products,
'search_term': query,
'current_categories': categories,
'current_sorting': current_sorting,
}
return render(request, 'products/products.html', context)
def product_detail(request, product_id):
product = get_object_or_404(Product, pk=product_id)
if request.method == 'POST':
rating = request.POST.get('rating', 3)
content = request.POST.get('content', '')
Review.objects.create(
product=product,
rating=rating,
content=content,
created_by=request.user
)
# redirect to the same page
return redirect('product_detail', product_id=product_id)
reviews = Review.objects.filter(product=product).order_by('-id')
context = {
'product': product,
'reviews': reviews
}
return render(request, 'products/product_detail.html', context)
型号
from django.db import models
from django.contrib.auth.models import User
class Category(models.Model):
class Meta:
verbose_name_plural = 'Categories'
name = models.CharField(max_length=254)
friendly_name = models.CharField(max_length=254, null=True, blank=True)
def __str__(self):
return self.name
def get_friendly_name(self):
return self.friendly_name
class Product(models.Model):
category = models.ForeignKey('Category', null=True, blank=True, on_delete=models.SET_NULL)
sku = models.CharField(max_length=254, null=True, blank=True)
name = models.CharField(max_length=254)
description = models.TextField()
price = models.DecimalField(max_digits=6, decimal_places=2)
rating = models.DecimalField(max_digits=6, decimal_places=2, null=True, blank=True)
image_url = models.URLField(max_length=1024, null=True, blank=True)
image = models.ImageField(null=True, blank=True)
def __str__(self):
return self.name
def get_rating(self):
reviews_total = 0
for review in self.reviews.all():
reviews_total += review.rating
if reviews_total > 0:
return reviews_total / self.reviews.count()
return 0
class Review(models.Model):
product = models.ForeignKey(Product, related_name='reviews', on_delete=models.CASCADE)
content = models.TextField()
created_by = models.ForeignKey(User, related_name='reviews', on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
RATINGS = ((1, '1'), (2, '2'), (3, '3'), (4, '4'), (5, '5'))
rating = models.IntegerField(default=RATINGS[2], choices=RATINGS)
def __str__(self):
return '%s - %s' % (self.product.name, self.created_by)
products.html模板
{% extends "base.html" %}
{% load static %}
{% block page_header %}
<div class="container header-container">
<div class="row">
<div class="col"></div>
</div>
</div>
{% endblock %}
{% block content %}
<div class="overlay"></div>
<div class="container-fluid">
<div class="row">
<div class="col text-center mt-3">
<h2 class="logo-font">Products</h2>
{% for c in current_categories %}
<a class="category-badge text-decoration-none" href="{% url 'products' %}?category={{ c.name }}">
<span class="p-2 mt-2 badge badge-white text-black rounded-0 border border-dark">{{ c.friendly_name }}</span>
</a>
{% endfor %}
<hr class="w-50 mb-1">
</div>
</div>
<div class="row">
<div class="product-container col-10 offset-1">
<div class="row mt-1 mb-2">
<div class="col-12 col-md-6 my-auto order-md-last d-flex justify-content-center justify-content-md-end">
<div class="sort-select-wrapper w-50">
<select id="sort-selector" class="custom-select custom-select-sm rounded-0 border border-{% if current_sorting != 'None_None' %}info{% else %}black{% endif %}">
<option value="reset" {% if current_sorting == 'None_None' %}selected{% endif %}>Sort by...</option>
<option value="price_asc" {% if current_sorting == 'price_asc' %}selected{% endif %}>Price (low to high)</option>
<option value="price_desc" {% if current_sorting == 'price_desc' %}selected{% endif %}>Price (high to low)</option>
<option value="rating_asc" {% if current_sorting == 'rating_asc' %}selected{% endif %}>Rating (low to high)</option>
<option value="rating_desc" {% if current_sorting == 'rating_desc' %}selected{% endif %}>Rating (high to low)</option>
<option value="name_asc" {% if current_sorting == 'name_asc' %}selected{% endif %}>Name (A-Z)</option>
<option value="name_desc" {% if current_sorting == 'name_desc' %}selected{% endif %}>Name (Z-A)</option>
<option value="category_asc" {% if current_sorting == 'category_asc' %}selected{% endif %}>Category (A-Z)</option>
<option value="category_desc" {% if current_sorting == 'category_desc' %}selected{% endif %}>Category (Z-A)</option>
</select>
</div>
</div>
<div class="col-12 col-md-6 order-md-first">
<p class="text-muted mt-3 text-center text-md-left">
{% if search_term or current_categories or current_sorting != 'None_None' %}
<span class="small"><a href="{% url 'products' %}">Products Home</a> | </span>
{% endif %}
{{ products|length }} Products{% if search_term %} found for <strong>"{{ search_term }}"</strong>{% endif %}
</p>
</div>
</div>
<div class="row">
{% for product in products %}
<div class="col-sm-6 col-md-6 col-lg-4 col-xl-3">
<div class="card h-100 border-0">
{% if product.image %}
<a href="{% url 'product_detail' product.id %}">
<img class="card-img-top img-fluid" src="{{ product.image.url }}" alt="{{ product.name }}">
</a>
{% else %}
<a href="{% url 'product_detail' product.id %}">
<img class="card-img-top img-fluid" src="{{ MEDIA_URL }}noimage.png" alt="{{ product.name }}">
</a>
{% endif %}
<div class="card-body pb-0">
<p class="mb-0">{{ product.name }}</p>
</div>
<div class="card-footer bg-white pt-0 border-0 text-left">
<div class="row">
<div class="col">
<p class="lead mb-0 text-left font-weight-bold">${{ product.price }}</p>
{% if product.category %}
<p class="small mt-1 mb-0">
<a class="text-muted" href="{% url 'products' %}?category={{ product.category.name }}">
<i class="fas fa-tag mr-1"></i>{{ product.category.friendly_name }}
</a>
</p>
{% endif %}
{% if product.get_rating > 0 %}
<small class="text-muted"><i class="fas fa-star mr-1" style=color:blue;></i>{{ product.get_rating|floatformat:1 }} / 5</small>
{% else %}
<small class="text-muted">No Rating</small>
{% endif %}
{% if request.user.is_superuser %}
<small class="ml-3">
<a href="{% url 'edit_product' product.id %}">Edit</a> |
<a class="text-danger" href="{% url 'delete_product' product.id %}">Delete</a>
</small>
{% endif %}
</div>
</div>
</div>
</div>
</div>
{% if forloop.counter|divisibleby:1 %}
<div class="col-12 d-sm-none mb-5">
<hr>
</div>
{% endif %}
{% if forloop.counter|divisibleby:2 %}
<div class="col-12 d-none d-sm-block d-md-block d-lg-none mb-5">
<hr>
</div>
{% endif %}
{% if forloop.counter|divisibleby:3 %}
<div class="col-12 d-none d-lg-block d-xl-none mb-5">
<hr>
</div>
{% endif %}
{% if forloop.counter|divisibleby:4 %}
<div class="col-12 d-none d-xl-block mb-5">
<hr>
</div>
{% endif %}
{% endfor %}
</div>
</div>
</div>
</div>
<div class="btt-button shadow-sm rounded-0 border border-black">
<a class="btt-link d-flex h-100">
<i class="fas fa-arrow-up text-black mx-auto my-auto"></i>
</a>
</div>
{% include 'newsletter/newsletter.html' %}
{% endblock %}
{% block postloadjs %}
{{ block.super }}
<script type="text/javascript">
$('.btt-link').click(function(e) {
window.scrollTo(0,0)
})
</script>
<script type="text/javascript">
$('#sort-selector').change(function() {
var selector = $(this);
var currentUrl = new URL(window.location);
var selectedVal = selector.val();
if(selectedVal != "reset"){
var sort = selectedVal.split("_")[0];
var direction = selectedVal.split("_")[1];
currentUrl.searchParams.set("sort", sort);
currentUrl.searchParams.set("direction", direction);
window.location.replace(currentUrl);
} else {
currentUrl.searchParams.delete("sort");
currentUrl.searchParams.delete("direction");
window.location.replace(currentUrl);
}
})
</script>
{% endblock %}
Am trying to setup so my products on the products site can be sorted by the rating high-low and low-high and show the none rated behind them. I cant seem to figure it out so any help would be appreciated. I added the code ithink is needed if you need anything more i will add it.
Thanks in advance.
I want when sorting by high to low it has the review with the highest rating first and if it dosent have any rating it goes to the far back behind the ones with any rating.
I want it to have the lowest rated ones first then the none rated ones at the last after the rated ones.
views.py
from django.shortcuts import render, redirect, reverse, get_object_or_404
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.db.models import Q
from django.db.models.functions import Lower
from .models import Product, Category, Review
from .forms import ProductForm, ReviewForm
# Create your views here.
def all_products(request):
""" A view to show all products, including sorting and search queries """
products = Product.objects.all()
query = None
categories = None
sort = None
direction = None
if request.GET:
if 'sort' in request.GET:
sortkey = request.GET['sort']
sort = sortkey
if sortkey == 'name':
sortkey = 'lower_name'
products = products.annotate(lower_name=Lower('name'))
if sortkey == 'category':
sortkey = 'category__name'
if 'direction' in request.GET:
direction = request.GET['direction']
if direction == 'desc':
sortkey = f'-{sortkey}'
products = products.order_by(sortkey)
if 'category' in request.GET:
categories = request.GET['category'].split(',')
products = products.filter(category__name__in=categories)
categories = Category.objects.filter(name__in=categories)
if 'q' in request.GET:
query = request.GET['q']
if not query:
messages.error(request, "You didn't enter any search criteria!")
return redirect(reverse('products'))
queries = Q(name__icontains=query) | Q(description__icontains=query)
products = products.filter(queries)
current_sorting = f'{sort}_{direction}'
context = {
'products': products,
'search_term': query,
'current_categories': categories,
'current_sorting': current_sorting,
}
return render(request, 'products/products.html', context)
def product_detail(request, product_id):
product = get_object_or_404(Product, pk=product_id)
if request.method == 'POST':
rating = request.POST.get('rating', 3)
content = request.POST.get('content', '')
Review.objects.create(
product=product,
rating=rating,
content=content,
created_by=request.user
)
# redirect to the same page
return redirect('product_detail', product_id=product_id)
reviews = Review.objects.filter(product=product).order_by('-id')
context = {
'product': product,
'reviews': reviews
}
return render(request, 'products/product_detail.html', context)
models.py
from django.db import models
from django.contrib.auth.models import User
class Category(models.Model):
class Meta:
verbose_name_plural = 'Categories'
name = models.CharField(max_length=254)
friendly_name = models.CharField(max_length=254, null=True, blank=True)
def __str__(self):
return self.name
def get_friendly_name(self):
return self.friendly_name
class Product(models.Model):
category = models.ForeignKey('Category', null=True, blank=True, on_delete=models.SET_NULL)
sku = models.CharField(max_length=254, null=True, blank=True)
name = models.CharField(max_length=254)
description = models.TextField()
price = models.DecimalField(max_digits=6, decimal_places=2)
rating = models.DecimalField(max_digits=6, decimal_places=2, null=True, blank=True)
image_url = models.URLField(max_length=1024, null=True, blank=True)
image = models.ImageField(null=True, blank=True)
def __str__(self):
return self.name
def get_rating(self):
reviews_total = 0
for review in self.reviews.all():
reviews_total += review.rating
if reviews_total > 0:
return reviews_total / self.reviews.count()
return 0
class Review(models.Model):
product = models.ForeignKey(Product, related_name='reviews', on_delete=models.CASCADE)
content = models.TextField()
created_by = models.ForeignKey(User, related_name='reviews', on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
RATINGS = ((1, '1'), (2, '2'), (3, '3'), (4, '4'), (5, '5'))
rating = models.IntegerField(default=RATINGS[2], choices=RATINGS)
def __str__(self):
return '%s - %s' % (self.product.name, self.created_by)
products.html template
{% extends "base.html" %}
{% load static %}
{% block page_header %}
<div class="container header-container">
<div class="row">
<div class="col"></div>
</div>
</div>
{% endblock %}
{% block content %}
<div class="overlay"></div>
<div class="container-fluid">
<div class="row">
<div class="col text-center mt-3">
<h2 class="logo-font">Products</h2>
{% for c in current_categories %}
<a class="category-badge text-decoration-none" href="{% url 'products' %}?category={{ c.name }}">
<span class="p-2 mt-2 badge badge-white text-black rounded-0 border border-dark">{{ c.friendly_name }}</span>
</a>
{% endfor %}
<hr class="w-50 mb-1">
</div>
</div>
<div class="row">
<div class="product-container col-10 offset-1">
<div class="row mt-1 mb-2">
<div class="col-12 col-md-6 my-auto order-md-last d-flex justify-content-center justify-content-md-end">
<div class="sort-select-wrapper w-50">
<select id="sort-selector" class="custom-select custom-select-sm rounded-0 border border-{% if current_sorting != 'None_None' %}info{% else %}black{% endif %}">
<option value="reset" {% if current_sorting == 'None_None' %}selected{% endif %}>Sort by...</option>
<option value="price_asc" {% if current_sorting == 'price_asc' %}selected{% endif %}>Price (low to high)</option>
<option value="price_desc" {% if current_sorting == 'price_desc' %}selected{% endif %}>Price (high to low)</option>
<option value="rating_asc" {% if current_sorting == 'rating_asc' %}selected{% endif %}>Rating (low to high)</option>
<option value="rating_desc" {% if current_sorting == 'rating_desc' %}selected{% endif %}>Rating (high to low)</option>
<option value="name_asc" {% if current_sorting == 'name_asc' %}selected{% endif %}>Name (A-Z)</option>
<option value="name_desc" {% if current_sorting == 'name_desc' %}selected{% endif %}>Name (Z-A)</option>
<option value="category_asc" {% if current_sorting == 'category_asc' %}selected{% endif %}>Category (A-Z)</option>
<option value="category_desc" {% if current_sorting == 'category_desc' %}selected{% endif %}>Category (Z-A)</option>
</select>
</div>
</div>
<div class="col-12 col-md-6 order-md-first">
<p class="text-muted mt-3 text-center text-md-left">
{% if search_term or current_categories or current_sorting != 'None_None' %}
<span class="small"><a href="{% url 'products' %}">Products Home</a> | </span>
{% endif %}
{{ products|length }} Products{% if search_term %} found for <strong>"{{ search_term }}"</strong>{% endif %}
</p>
</div>
</div>
<div class="row">
{% for product in products %}
<div class="col-sm-6 col-md-6 col-lg-4 col-xl-3">
<div class="card h-100 border-0">
{% if product.image %}
<a href="{% url 'product_detail' product.id %}">
<img class="card-img-top img-fluid" src="{{ product.image.url }}" alt="{{ product.name }}">
</a>
{% else %}
<a href="{% url 'product_detail' product.id %}">
<img class="card-img-top img-fluid" src="{{ MEDIA_URL }}noimage.png" alt="{{ product.name }}">
</a>
{% endif %}
<div class="card-body pb-0">
<p class="mb-0">{{ product.name }}</p>
</div>
<div class="card-footer bg-white pt-0 border-0 text-left">
<div class="row">
<div class="col">
<p class="lead mb-0 text-left font-weight-bold">${{ product.price }}</p>
{% if product.category %}
<p class="small mt-1 mb-0">
<a class="text-muted" href="{% url 'products' %}?category={{ product.category.name }}">
<i class="fas fa-tag mr-1"></i>{{ product.category.friendly_name }}
</a>
</p>
{% endif %}
{% if product.get_rating > 0 %}
<small class="text-muted"><i class="fas fa-star mr-1" style=color:blue;></i>{{ product.get_rating|floatformat:1 }} / 5</small>
{% else %}
<small class="text-muted">No Rating</small>
{% endif %}
{% if request.user.is_superuser %}
<small class="ml-3">
<a href="{% url 'edit_product' product.id %}">Edit</a> |
<a class="text-danger" href="{% url 'delete_product' product.id %}">Delete</a>
</small>
{% endif %}
</div>
</div>
</div>
</div>
</div>
{% if forloop.counter|divisibleby:1 %}
<div class="col-12 d-sm-none mb-5">
<hr>
</div>
{% endif %}
{% if forloop.counter|divisibleby:2 %}
<div class="col-12 d-none d-sm-block d-md-block d-lg-none mb-5">
<hr>
</div>
{% endif %}
{% if forloop.counter|divisibleby:3 %}
<div class="col-12 d-none d-lg-block d-xl-none mb-5">
<hr>
</div>
{% endif %}
{% if forloop.counter|divisibleby:4 %}
<div class="col-12 d-none d-xl-block mb-5">
<hr>
</div>
{% endif %}
{% endfor %}
</div>
</div>
</div>
</div>
<div class="btt-button shadow-sm rounded-0 border border-black">
<a class="btt-link d-flex h-100">
<i class="fas fa-arrow-up text-black mx-auto my-auto"></i>
</a>
</div>
{% include 'newsletter/newsletter.html' %}
{% endblock %}
{% block postloadjs %}
{{ block.super }}
<script type="text/javascript">
$('.btt-link').click(function(e) {
window.scrollTo(0,0)
})
</script>
<script type="text/javascript">
$('#sort-selector').change(function() {
var selector = $(this);
var currentUrl = new URL(window.location);
var selectedVal = selector.val();
if(selectedVal != "reset"){
var sort = selectedVal.split("_")[0];
var direction = selectedVal.split("_")[1];
currentUrl.searchParams.set("sort", sort);
currentUrl.searchParams.set("direction", direction);
window.location.replace(currentUrl);
} else {
currentUrl.searchParams.delete("sort");
currentUrl.searchParams.delete("direction");
window.location.replace(currentUrl);
}
})
</script>
{% endblock %}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论