Преобразование рейтинга в звезды в шаблоне Django - PullRequest
0 голосов
/ 01 апреля 2019

Я работаю над проектом, использующим Python (3.7) и Django (2.1), в котором я хочу отображать среднюю оценку результатов из представления внутри шаблона Django.

Вот что я пробовал до сих пор:

От models.py:

class Gig(models.Model):
    CATEGORY_CHOICES = (
        ('GD', 'Graphic & Design'),
        ('DM', 'Digital Marketing'),
        ('WT', 'Writing & Translation'),
        ('VA', 'Video & Animation'),
        ('MA', 'Music & Audio'),
        ('PT', 'Programming & Tech'),
        ('FL', 'Fun & 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 Ответ

1 голос
/ 01 апреля 2019

У вас есть несколько альтернатив, таких как django-star-rating , или вы можете использовать несколько библиотек JS как star-rating или starability .

Я предоставлю свое решение, используя стабильность, хотя оно может быть основано на мнении.

В вашем шаблоне:

Включить стили в тег 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 к целому числу, и я предлагаю вам сделать это в представлении.

Основная проблема устойчивости заключается в том, что он не поддерживает половину звезд, но если вы не слишком заботитесь об этом, вы можете использовать следующее для округления среднего

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')))

Для получения дополнительной информации, если вы решите ее использовать, я рекомендую вам проверить документацию о стабильности .

...