#python #django #python-3.x #django-2.1
#python #django #python-3.x #django-2.1
Вопрос:
Я работаю над проектом с использованием Python (3.7) и Django (2.1), в котором я хочу отобразить среднюю оценку, возвращаемую из представления внутри шаблона Django.
Вот что я пробовал до сих пор:
От models.py
:
class Gig(models.Model):
CATEGORY_CHOICES = (
('GD', 'Graphic amp; Design'),
('DM', 'Digital Marketing'),
('WT', 'Writing amp; Translation'),
('VA', 'Video amp; Animation'),
('MA', 'Music amp; Audio'),
('PT', 'Programming amp; Tech'),
('FL', 'Fun amp; Lifestyle'),
)
title = models.CharField(max_length=500)
category = models.CharField(max_length=255, choices=CATEGORY_CHOICES)
description = models.CharField(max_length=1000)
price = models.IntegerField(blank=False)
photo = models.FileField(upload_to='gigs')
status = models.BooleanField(default=True)
user = models.ForeignKey(User, on_delete=models.CASCADE)
created_at = models.DateTimeField(default=timezone.now)
def __str__(self):
return self.title
class GigReview(models.Model):
RATING_RANGE = (
('1', '1'),
('2', '2'),
('3', '3'),
('4', '4'),
('5', '5')
)
user = models.ForeignKey(User, on_delete=models.CASCADE)
gig = models.ForeignKey(Gig, on_delete=models.CASCADE, related_name='rates')
order = models.ForeignKey(Order, on_delete=models.CASCADE, null=True)
rating = models.IntegerField(choices=RATING_RANGE,)
content = models.CharField(max_length=500)
def __str__(self):
return self.content
От views.py
:
def home(request):
gigs = Gig.objects.filter(status=True).annotate(avg_review=Avg('rates__rating'))
return render(request, 'home.html', {'gigs': gigs})
Итак, теперь у каждого gig
есть средний рейтинг, и я хочу отобразить звезды в качестве рейтинга внутри шаблона.
От home.html
:
{% for gig in gigs %}
<div data-marker-id="59c0c8e33b1527bfe2abaf92" class="col-sm-6 col-xl-4 mb-5">
<div class="card h-100 border-0 shadow">
<div style="background-image: url(/media/{{ gig.photo }}); min-height: 200px;"
class="card-img-top overflow-hidden dark-overlay bg-cover">
<a href="{% url 'gig-detail' gig.id %}" class="tile-link"></a>
<div class="card-img-overlay-bottom z-index-20"></div>
<div class="card-img-overlay-top d-flex justify-content-between align-items-center">
<div class="badge badge-transparent badge-pill px-3 py-2">{{ git.category }}</div>
<a href="javascript: void();" class="card-fav-icon position-relative z-index-40">
<svg class="svg-icon text-white">
<use xlink:href="#heart-1"></use>
</svg>
</a>
</div>
</div>
<div class="card-body">
<h6 class="text-shadow"><a href="{% url 'gig-detail' gig.id %}"
style="text-decoration: none; color: black">
{{ gig.title }}</a></h6>
<p class="mb-2 text-xs" id="stars">
{{ gig.avg_review }}
{% if gig.avg_review is not None %}
{{ gig.avg_review }}
{% endif %}
<i class="fa fa-star text-warning"></i>
<i class="fa fa-star text-warning"></i>
<i class="fa fa-star text-warning"></i>
<i class="fa fa-star text-warning"></i>
<i class="fa fa-star text-gray-300"></i>
</p>
<p class="text-sm text-muted mb-3">{{ gig.description|slice:"20" }}...</p>
<p class="text-sm text-muted text-uppercase mb-1">
<span>By <a href="{% url 'profile' gig.user.username %}"
class="text-dark">{{ gig.user }}</a></span>
<span class="float-right"><b class="text-shadow text-lg"
style="color: black;">${{ gig.price }}</b></span>
</p>
</div>
</div>
</div>
{% endfor %}
Итак, как я могу отобразить средний рейтинг каждого gig
в виде звезд, заполненных рейтингом?
Заранее спасибо!
Комментарии:
1. не
gig.avg_review
работает?2. да, он выводит средний рейтинг, подобный
3.5
илиNone
, если концерт еще не оценен!3. итак, смысл в том, чтобы отображать звезды вместо чисел, не так ли?
4. да, точно, вы правы!
5. Если это так, я использовал django-star-rating или вы могли бы использовать несколько библиотек JS в качестве звездного рейтинга
Ответ №1:
У вас есть несколько альтернатив, например, использование django-star-rating или вы могли бы использовать несколько библиотек JS в качестве звездности или доступности.
Я предоставлю свое решение, используя проверяемость, хотя это может быть в первую очередь основано на мнении.
В вашем шаблоне:
Включите стили в head
тег
<link rel="stylesheet" type="text/css" href="css/starability-all.min.css"/>
и используйте следующее:
<fieldset class="starability-result mx-auto" data-rating="{{ gig.avg_review }}">
Rated: {{ gig.avg_review }} stars
</fieldset>
Возможно, вам потребуется преобразовать gig.avg_review
в целое число, и я предлагаю вам сделать это в представлении.
Основная проблема проверяемости заключается в том, что она не поддерживает значение half stars, но если вас это не слишком волнует, вы можете использовать следующее, чтобы округлить среднее значение
from django.db.models import Func
class Round(Func):
function = 'ROUND'
template='%(function)s(%(expressions)s, 0)'
Теперь примените это к вашему запросу:
gigs = Gig.objects.filter(status=True).annotate(avg_review=Round(Avg('rates__rating')))
Для получения дополнительной информации, на случай, если вы решите ее использовать, я рекомендую вам ознакомиться с документацией starability.
Комментарии:
1. Как мы можем получить оценку обратно из шаблонов, если кто-то поставил оценку? Я знаю часть javascript, но на что мне следует обратить внимание?