Здравствуйте, я вернулся, и на этот раз я здесь, чтобы помочь вам в создании рейтинговой системы, аналогичной той, что есть в магазине Play. Предпосылками для этого являются знания HTML, CSS, Bootstrap (не требуется), Flask (или любого другого удобного вам серверного интерфейса) и jQuery. Для хранения данных нам потребуется JSON. Вот и все, поехали.

Рабочая страница будет выглядеть примерно так, как показано ниже.

Базовый интерфейс

Для начала создайте папку с именем starRating и создайте простое приложение-флягу. Я назвал свой рейтинг rating.py.

from flask import Flask, url_for, render_template
app = Flask(__name__)
@app.route('/')
def home():
   return render_template('star_rating.html')
if __name__ == "__main__":
app.run(debug=True)

Файл star_rating.html содержит базовый HTML и CSS. Это могло выглядеть примерно так.

Затем в статической папке (в которой уже есть каталог с именем css) мы добавляем еще два каталога: js и изображения. Есть набор изображений, которые мы собираемся использовать, и ссылка GitHub на этот репозиторий будет предоставлена ​​в конце. Чтобы избежать путаницы в названиях, ниже представлены изображения.

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

Сначала добавьте следующий код на свою страницу star_rating.html.

<div class="text-center">
{% for i in range(5) %}
<img src="{{ url_for('static',filename='images/rating.png') }}" width="50" height="50" id="star_{{i}}">
{% endfor %}
&nbsp;&nbsp;
<img class="mt-2" id="ratings" src="{{ url_for('static', filename='images/neutral.png') }}" width="60" height="50">
</div>

Таким образом, приведенный выше код просто делает это:

По сути, мы пять раз создавали изображение пустой звезды, используя цикл for в jinja2, каждый раз присваивая ему отдельный идентификатор. Затем кодовый блок добавляет два неразрывных пробела, а затем нейтральное изображение лица.

Теперь для создания функциональности нам потребуется jQuery. Итак, создайте файл с именем rating.js в папке js. Чтобы дать общее представление, код jQuery будет определять изменение пустой звезды на заполненную, когда пользователь щелкает любую из звездочек. Хорошо, не надо больше хвастаться, вернемся к коду. Чтобы код jQuery, который вы пишете, работал, вы должны включить его в раздел HTML-скрипта. Есть много CDN, которые предлагают это. Для вашего удобства просто скопируйте следующий код и добавьте его в раздел скриптов вашего HTML.

<script src="https://code.jquery.com/jquery-3.6.0.js" integrity="sha256-H+K7U5CnXl1h5ywQfKtSj8PCmoN9aaq30gDh27Xc0jk=" crossorigin="anonymous"></script>

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

$('#star_0').click(function(){
$('#star_0').attr("src", "../../static/images/rating_fill.png");
$('#star_1').attr("src", "../../static/images/rating.png");
$('#star_2').attr("src", "../../static/images/rating.png");
$('#star_3').attr("src", "../../static/images/rating.png");
$('#star_4').attr("src", "../../static/images/rating.png");
$('#ratings').attr("src","../../static/images/x_unhappy.png");
});
$('#star_1').click(function(){
$('#star_0').attr("src", "../../static/images/rating_fill.png");
$('#star_1').attr("src", "../../static/images/rating_fill.png");
$('#star_2').attr("src", "../../static/images/rating.png");
$('#star_3').attr("src", "../../static/images/rating.png");
$('#star_4').attr("src", "../../static/images/rating.png");
$('#ratings').attr("src","../../static/images/unhappy.png");
});
$('#star_2').click(function(){
$('#star_0').attr("src", "../../static/images/rating_fill.png");
$('#star_1').attr("src", "../../static/images/rating_fill.png");
$('#star_2').attr("src", "../../static/images/rating_fill.png");
$('#star_3').attr("src", "../../static/images/rating.png");
$('#star_4').attr("src", "../../static/images/rating.png");
$('#ratings').attr("src","../../static/images/ok.png");
});
$('#star_3').click(function(){
$('#star_0').attr("src", "../../static/images/rating_fill.png");
$('#star_1').attr("src", "../../static/images/rating_fill.png");
$('#star_2').attr("src", "../../static/images/rating_fill.png");
$('#star_3').attr("src", "../../static/images/rating_fill.png");
$('#star_4').attr("src", "../../static/images/rating.png");
$('#ratings').attr("src","../../static/images/happy.png");
});
$('#star_4').click(function(){
$('#star_0').attr("src", "../../static/images/rating_fill.png");
$('#star_1').attr("src", "../../static/images/rating_fill.png");
$('#star_2').attr("src", "../../static/images/rating_fill.png");
$('#star_3').attr("src", "../../static/images/rating_fill.png");
$('#star_4').attr("src", "../../static/images/rating_fill.png");
$('#ratings').attr("src","../../static/images/xtrahappy.png");
});

Этот код определяет, что произойдет при нажатии на одну звездочку для всех пяти звезд. Изображения также будут соответственно анимированы. Для вашего понимания я хотел бы объяснить код для третьей звезды («# star_2»), поскольку в нем все элементы одинаковы. Таким образом, событие клика для «# star_2» запускается в тот момент, когда мы нажимаем третью звездочку. Код просто добавляет желтую заливку ко всем звездам перед ней, а также к самой третьей звезде, а остальным, чтобы потерять желтую заливку, если они уже заполнены. Вторая половина имеет смысл только в том случае, если вы сначала нажали, чтобы получить рейтинг в пять звезд, но затем передумали снизить его до трех (после того, как вспомнили, что приложение было опубликовано вашим врагом!). В любом случае приведенный выше код будет делать следующее:

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

Сначала мы добавляем кнопку отправки вместе с полем input type = hidden. Причина этого будет объяснена немного позже.

<div class="text-center">
<form method='POST' action="">
<input type="hidden" id="rating_content" name='rating' value='0'>
<input type="submit" id="submitbtn" class="btn btn-primary mt-2" value="Submit my Rating">
</form>
</div>

Страница star_rating.html теперь должна выглядеть следующим образом:

Итак, кнопка отправки отправляет данные в бэкэнд. И скрытый тег будет здесь самым важным, поскольку он будет отображать звездные рейтинги со значением от 1 до 5. Отсюда и причина, по которой он был добавлен в форму!

Сопоставление звездного рейтинга с числами 1–5

Правильно, Хо! Теперь мы можем добавить код для сопоставления рейтингов со значениями в диапазоне от 1 до 5. Его можно добавить в сам файл rating.js.

Чтобы сделать это более понятным, например, если вы решите поставить оценку в 4 звезды, вы, естественно, нажмете четвертую звезду на экране. Поэтому, когда обрабатывается событие щелчка для четвертой звезды, мы можем просто изменить значение скрытого элемента ввода на «4». Точно так же, когда вы нажимаете пятую звездочку, значение элемента ввода становится «5» и так далее! Надеюсь, это проясняет логику.

Теперь код просто вносит изменения в приведенный выше рейтинг rating.js как:

$('#star_0').click(function(){
$('#star_0').attr("src", "../../static/images/rating_fill.png");
$('#star_1').attr("src", "../../static/images/rating.png");
$('#star_2').attr("src", "../../static/images/rating.png");
$('#star_3').attr("src", "../../static/images/rating.png");
$('#star_4').attr("src", "../../static/images/rating.png");
$('#ratings').attr("src","../../static/images/x_unhappy.png");
$('#rating_content').attr('value','1');
});
$('#star_1').click(function(){
$('#star_0').attr("src", "../../static/images/rating_fill.png");
$('#star_1').attr("src", "../../static/images/rating_fill.png");
$('#star_2').attr("src", "../../static/images/rating.png");
$('#star_3').attr("src", "../../static/images/rating.png");
$('#star_4').attr("src", "../../static/images/rating.png");
$('#ratings').attr("src","../../static/images/unhappy.png");
$('#rating_content').attr('value','2');
});
$('#star_2').click(function(){
$('#star_0').attr("src", "../../static/images/rating_fill.png");
$('#star_1').attr("src", "../../static/images/rating_fill.png");
$('#star_2').attr("src", "../../static/images/rating_fill.png");
$('#star_3').attr("src", "../../static/images/rating.png");
$('#star_4').attr("src", "../../static/images/rating.png");
$('#ratings').attr("src","../../static/images/ok.png");
$('#rating_content').attr('value','3');
});
$('#star_3').click(function(){
$('#star_0').attr("src", "../../static/images/rating_fill.png");
$('#star_1').attr("src", "../../static/images/rating_fill.png");
$('#star_2').attr("src", "../../static/images/rating_fill.png");
$('#star_3').attr("src", "../../static/images/rating_fill.png");
$('#star_4').attr("src", "../../static/images/rating.png");
$('#ratings').attr("src","../../static/images/happy.png");
$('#rating_content').attr('value','4');
});
$('#star_4').click(function(){
$('#star_0').attr("src", "../../static/images/rating_fill.png");
$('#star_1').attr("src", "../../static/images/rating_fill.png");
$('#star_2').attr("src", "../../static/images/rating_fill.png");
$('#star_3').attr("src", "../../static/images/rating_fill.png");
$('#star_4').attr("src", "../../static/images/rating_fill.png");
$('#ratings').attr("src","../../static/images/xtrahappy.png");
$('#rating_content').attr('value','5');
});

Обратите внимание на последние строки события щелчка для каждой звезды.

Сохранение звездных оценок с помощью Flask в файле JSON

Теперь перейдем к складской части. Это будет очень просто для этого поста в виде файла JSON. Но предположим, что вы хотите добавить это в базу данных, тогда это также можно легко сделать с помощью SQLAlchemy.

Хотя следующие инструкции будут в основном относиться к Flask, если вы являетесь пользователем Django, вам будет легко, потому что код Python будет одинаковым для них обоих, для работы с файлом JSON. Если вы тот, кто использует Laravel. , NodeJS и т. Д., Даже в этом случае вы также сможете продолжить, внося соответствующие изменения в код.

Прежде всего, давайте создадим файл JSON, помимо rating.py, и сохраним его как rating_so_far.json. Код будет просто:

{
"five_stars":"0",
"four_stars":"0",
"three_stars":"0",
"two_stars":"0",
"one_star":"0",
"count":"0",
"total":"0",
"rating": "0.0"
}

Итак, механизм хранения готов, и все, что он показывает, - это количество оценок для каждого уровня, количество голосов, общее значение путем добавления всех оценок, а также рейтинг в виде значения с плавающей запятой. Теперь в файле rating.py нам нужно импортировать пару вещей: сначала модуль запроса из фляги, а затем модуль json для работы с нашим файлом JSON.

from flask import Flask, url_for, render_template,request
import json

Теперь каждый раз, когда мы нажимаем на любую из 5 звездочек, нам нужно увеличивать соответствующее значение json на 1. Кроме того, для работы с данными JSON нам сначала нужно преобразовать их в объекты Python. Здесь решающую роль играют методы json.load и json.dump (json.loads и json.dump играют решающую роль при работе со строкой, отформатированной как данные JSON). Приступим к работе.

Функция просмотра, которую мы написали ранее, теперь будет похожа на:

Итак, как видите, наработано довольно много мышц! Не волнуйтесь, давайте рассмотрим это строка за строкой.

  1. Во-первых, мы заставляем функцию просмотра также принимать запросы POST, и это то, что мы делаем в строке 6, добавляя методы = [‘GET’, ‘POST’].
  2. Строка 8: Теперь, используя диспетчер контекста (с оператором), мы открываем созданный файл JSON. Поскольку он прав, помимо нашего файла python, мы просто передаем его имя методу open и открываем его в режиме чтения (по умолчанию). Указатель на файл называется f.

  1. В строке 9 мы сохраняем данные JSON в объекте Python с именем ratingstore. Созданный объект по умолчанию является словарем Python.
  2. Строка 10: мы проверяем, был ли отправлен запрос на публикацию, т. Е. Была ли нажата кнопка отправки формы. Таким образом, следующий код будет запущен только в том случае, если была нажата кнопка отправки.
  3. Строки 11–18 показывают присвоение значений словаря переменным. Переменные называются так же, как ключи, чтобы избежать путаницы.
  4. Строка 19 проверяет, есть ли у нас элемент ввода с именем «рейтинг» в только что отправленной форме. Если вы помните, это имя, которое мы дали скрытому элементу ввода! (Приведенное значение было 0)
  5. Строка 20 преобразует значение скрытого элемента ввода и присваивает его переменной с именем content. Значение любого элемента формы, имя которого известно, можно получить, как показано, или также с помощью request.form.get («input_element_name»).
  6. Строка 21 проверяет, является ли содержимое пустым или нет. Если нет, то продолжим.
  7. Строка 22–31: в зависимости от того, сколько звездочек мы выбрали, значение скрытого элемента ввода уже изменилось. Эти строки проверяют значение и увеличивают соответствующую переменную на единицу. То есть каждый голос регистрируется в этих переменных! А что, если вы чувствуете желание сдаться, не выбирая звездочек? Что ж, сделай это и расскажи мне, какие изменения ты наблюдаешь.
  8. Строка 32: Мы увеличиваем количество оценок на 1.
  9. Строка 33: Увеличьте общее значение со значением содержания. Это очень важно для расчета рейтинговых баллов.
  10. Строка 34: Найдите рейтинг, разделив сумму на количество голосов. Также мы используем тег формата, чтобы ограничить рейтинг до одной десятичной точки.
  11. Строка 35–42: Измените значение хранилища рейтингов словаря, добавив новые значения.
  12. Строка 43: Откройте файл JSON в режиме записи (да, существующие в нем данные будут удалены).
  13. Строка 44: json. Дамп хранилища рейтингов словаря Python в наш файл JSON. Аргумент indent = 2 форматирует файл в удобочитаемом формате.

Вот как вы сохраняете изменения в файле JSON. Но открытие файла JSON для просмотра данных каждый раз может быть утомительным. Здесь мы создаем новую программу просмотра звездного рейтинга, похожую на Play Store (поверьте, скоро я заткнусь).

Отображение оценок в Google Play!

Для просмотра рейтингов в режиме реального времени нам нужно немного поработать. Есть HTML, CSS, а также код Javascript. Давайте сначала займемся HTML и CSS.

Ниже приведен HTML-код, который вам нужно добавить:

<div class="text-center">
<h1>{{rating}}</h1>
<div id="display_rating">
<div class="row align-items-center">
<div class="offset-1 col-1 mt-3">
<p style="font-size: 14px;">5</p>
</div>
<div class="col-8">
<div class="content_5_star_outer">
<div class="content_5_star_inner">nn</div>
</div>
</div>
</div>
<div class="row align-items-center inner-ratings">
<div class="offset-1 col-1 mt-3">
<p style="font-size: 14px;">4</p>
</div>
<div class="col-8">
<div class="content_4_star_outer">
<div class="content_4_star_inner">nn</div>
</div>
</div>
</div>
<div class="row align-items-center inner-ratings">
<div class="offset-1 col-1 mt-3">
<p style="font-size: 14px;">3</p>
</div>
<div class="col-8">
<div class="content_3_star_outer">
<div class="content_3_star_inner">nn</div>
</div>
</div>
</div>
<div class="row align-items-center inner-ratings">
<div class="offset-1 col-1 mt-3">
<p style="font-size: 14px;">2</p>
</div>
<div class="col-8">
<div class="content_2_star_outer">
<div class="content_2_star_inner">nn</div>
</div>
</div>
</div>
<div class="row align-items-center inner-ratings">
<div class="offset-1 col-1 mt-3">
<p style="font-size: 14px;">1</p>
</div>
<div class="col-8">
<div class="content_1_star_outer">
<div class="content_1_star_inner">nn</div>
</div>
</div>
</div>
</div>
</div>

Вы скоро поймете, почему мы добавили рейтинг как переменную jinja2. А пока продолжайте.

Ниже приведен код CSS:

.content_5_star_inner{
border: solid 1px green;
background-color: green;
color: transparent;
font-size: 5px;
border-radius: 5px;
width: 0%;
}
.content_5_star_outer{
/*border: solid 1px grey;*/
background-color: lightgrey;
color: transparent;
font-size: 5px;
border-radius: 5px;
}
.content_4_star_inner{
border: solid 1px green;
background-color: green;
color: transparent;
font-size: 5px;
border-radius: 5px;
width: 0%;
}
.content_4_star_outer{
/*border: solid 1px grey;*/
background-color: lightgrey;
color: transparent;
font-size: 5px;
border-radius: 5px;
}
.content_3_star_inner{
border: solid 1px green;
background-color: green;
color: transparent;
font-size: 5px;
border-radius: 5px;
width: 0%;
}
.content_3_star_outer{
/*border: solid 1px grey;*/
background-color: lightgrey;
color: transparent;
font-size: 5px;
border-radius: 5px;
}
.content_2_star_inner{
border: solid 1px green;
background-color: green;
color: transparent;
font-size: 5px;
border-radius: 5px;
width: 0%;
}
.content_2_star_outer{
/*border: solid 1px grey;*/
background-color: lightgrey;
color: transparent;
font-size: 5px;
border-radius: 5px;
}
.content_1_star_inner{
border: solid 1px green;
background-color: green;
color: transparent;
font-size: 5px;
border-radius: 5px;
width: 0%;
}
.content_1_star_outer{
/*border: solid 1px grey;*/
background-color: lightgrey;
color: transparent;
font-size: 5px;
border-radius: 5px;
}
#display_rating{
margin-top: 25px;
margin-left: auto;
margin-right: auto;
width: 40%;
border: solid 4px green;
border-radius: 100%;
color: black;
background-color: white;
padding: 4em;
}

После добавления обоих вариантов страница будет выглядеть примерно так:

Я постараюсь вкратце объяснить, что я здесь сделал. По сути, есть 2 перекрывающихся прямоугольника: один серый, который находится внизу, а другой - зеленый прямоугольник, который находится над ним. Ширина внутреннего, то есть зеленого прямоугольника, будет варьироваться в зависимости от рейтинга, который получает каждый звездный уровень. Вот как мы в основном и будем работать.

Теперь, чтобы добавить окончательную функциональность, нам нужно создать еще один файл javascript с именем finale.js и сохранить его в папку js. Это предотвратит беспорядок и путаницу, а также это необходимо, поскольку мы должны передать переменные python, которые мы создали при публикации формы. Итак, давайте снова катимся!

Код javascript для finale.js:

function starBars(five_stars, four_stars, three_stars, two_stars, one_star,total_votes){
var content_5_width = (five_stars/total_votes)*100+'%';
var content_4_width = (four_stars/total_votes)*100+'%';
var content_3_width = (three_stars/total_votes)*100+'%';
var content_2_width = (two_stars/total_votes)*100+'%';
var content_1_width = (one_star/total_votes)*100+'%';
document.querySelector('.content_5_star_inner').style.width = content_5_width;
document.querySelector('.content_4_star_inner').style.width = content_4_width;
document.querySelector('.content_3_star_inner').style.width = content_3_width;
document.querySelector('.content_2_star_inner').style.width = content_2_width;
document.querySelector('.content_1_star_inner').style.width = content_1_width;
}

Этот код основан на фактическом принципе вычисления процента, то есть процента чего-то = (количество этого чего-то / общее число) * 100. Мы делаем это для каждого уровня и в равной степени применяем это для каждой ширины внутреннего прямоугольника, тем самым делая его динамичным для наших голосов.

Но теперь возникает проблема: как передать параметры, которые на самом деле доступны только в Python?

Это так же просто. Все, что нам нужно сделать, это передать эти параметры всякий раз, когда наша страница вызывается как запрос GET. Во Flask я могу просто передавать эти параметры всякий раз, когда я визуализирую шаблон star_rating.html (который можно увидеть в строке 45 изображения кода).

Итак, после добавления параметров они станут доступны в нашем HTML-коде, и мы сможем использовать их в шаблонах Jinja2.

return render_template(
'star_rating.html', 
five_stars=ratingstore['five_stars'], four_stars=ratingstore['four_stars'], three_stars=ratingstore['three_stars'], two_stars=ratingstore['two_stars'], one_star=ratingstore['one_star'], 
count=ratingstore['count'], 
rating=ratingstore['rating']
)

Имена никогда не меняются даже при передаче в качестве параметров. Это уменьшает для меня путаницу, и я думаю, что то же самое может относиться и к вам! Также теперь я надеюсь, вы поняли, как мне удалось включить {{rating}} в тег ‹h1›.

Теперь, когда в finale.js есть функция с именем starBars, давайте сначала вызовем ее, а затем вызовем функцию в отдельном скрипте.

Наконец, раздел сценария в star_rating.html должен выглядеть так:

<script src="{{ url_for('static',filename='js/rating.js') }}"></script>
<script src="{{ url_for('static',filename='js/finale.js') }}"></script>
<script>
starBars(
five_stars = '{{five_stars}}',
four_stars = '{{four_stars}}',
three_stars = '{{three_stars}}',
two_stars = '{{two_stars}}',
one_star = '{{one_star}}',
total_votes = '{{count}}'
)
</script>

Как видите, функция starBars будет вызываться с переменными Python (перекрестная проверка имен из render_template) в качестве аргументов. Поскольку это уже определено в finale.js, starBars будет работать без ошибок, а параметрам javascript будет передан аргумент переменной python.

И вот! Мы сделали. Чтобы убедиться, что все работает, я покажу вам живую демонстрацию того, что мы сделали. Бьюсь об заклад, вы останетесь довольны своими усилиями!

Большое спасибо, дорогой читатель, если ты терпеливо дочитал до этого места. Надеюсь, вы кое-что узнали о том, как создавать системы рейтинга в реальном времени. Также прошу прощения за качество GIF. Средний допускает только 25 МБ максимального размера изображения. Так что мне пришлось приспособиться к этому!

И да, репозиторий GitHub, как я могу это забыть! Весь код и ресурсы можно найти здесь.

Спасибо и до следующего поста, до свидания!