Определим представление в urls.py
Добавим обработку представления в urls.py нашего приложения blog:
from django.urls import path
from .views import PostListView, PostDetailView, PostFromCategory, PostCreateView, PostUpdateView, CommentCreateView, \
PostByTagListView, RatingCreateView
urlpatterns = [
path('', PostListView.as_view(), name='home'),
path('post/create/', PostCreateView.as_view(), name='post_create'),
path('post/<str:slug>/update/', PostUpdateView.as_view(), name='post_update'),
path('post/<str:slug>/', PostDetailView.as_view(), name='post_detail'),
path('post/<int:pk>/comments/create/', CommentCreateView.as_view(), name='comment_create_view'),
path('post/tags/<str:tag>/', PostByTagListView.as_view(), name='post_by_tags'),
path('category/<str:slug>/', PostFromCategory.as_view(), name="post_by_category"),
path('rating/', RatingCreateView.as_view(), name='rating'),
]
Создадим JavaScript для обработки рейтинга у статей/статьи
Ранее в уроках по созданию системы комментариев с помощью JavaScipt мы уже создавали подобные файлы и подключали, в разделе 11.2 Создание древовидных комментариев, добавление JavaScript , в нем мы создаем файл работы для csrftoken. Этот код может быть использован в других файлах JavaScript, если они ссылаются на этот код, где csrftoken доступен для использования.
Далее я создам файл ratings.js в папке templates/js/ со следующим кодом системы рейтинга:
const ratingButtons = document.querySelectorAll('.rating-buttons');
ratingButtons.forEach(button => {
button.addEventListener('click', event => {
// Получаем значение рейтинга из data-атрибута кнопки
const value = parseInt(event.target.dataset.value)
const postId = parseInt(event.target.dataset.post)
const ratingSum = button.querySelector('.rating-sum');
// Создаем объект FormData для отправки данных на сервер
const formData = new FormData();
// Добавляем id статьи, значение кнопки
formData.append('post_id', postId);
formData.append('value', value);
// Отправляем AJAX-Запрос на сервер
fetch("/rating/", {
method: "POST",
headers: {
"X-CSRFToken": csrftoken,
"X-Requested-With": "XMLHttpRequest",
},
body: formData
}).then(response => response.json())
.then(data => {
// Обновляем значение на кнопке
ratingSum.textContent = data.rating_sum;
})
.catch(error => console.error(error));
});
});
Данный код устанавливает обработчик кликов на кнопки рейтинга, которые имеют класс 'rating-buttons'. Когда пользователь кликает на одну из кнопок, происходит извлечение значения рейтинга из data-атрибута кнопки, а также id записи, которую пользователь оценил.
Затем создается объект FormData, который содержит эту информацию и отправляется AJAX-запрос на сервер с использованием метода fetch(). В заголовке запроса передается CSRF-токен и заголовок X-Requested-With со значением XMLHttpRequest.
После получения ответа сервера, значение суммарного рейтинга обновляется на кнопке с помощью метода textContent.
Добавление кнопок и обработка js на странице списка статей
Далее подключаем ratings.js в post_list.html и добавляем соответствующие кнопки для лайка, дизлайка и суммы рейтинга:
{% extends 'main.html' %}
{% block content %}
{% load static %}
{% for post in posts %}
<div class="card mb-3">
<div class="row">
<div class="col-4">
<img src="{{ post.thumbnail.url }}" class="card-img-top" alt="{{ post.title }}">
</div>
<div class="col-8">
<div class="card-body">
<h5 class="card-title">
<a href="{{ post.get_absolute_url }}">{{ post.title }}</a>
</h5>
<p class="card-text">{{ post.description|safe }}</p>
<small>Добавил {{ post.author.username }}, {{ post.create }},</small>
в категорию: <a href="{{ post.category.get_absolute_url }}">{{ post.category.title }}</a>
</div>
</div>
<div class="rating-buttons">
<button class="btn btn-sm btn-primary" data-post="{{ post.id }}" data-value="1">Лайк</button>
<button class="btn btn-sm btn-secondary" data-post="{{ post.id }}" data-value="-1">Дизлайк
</button>
<button class="btn btn-sm btn-secondary rating-sum">{{ post.get_sum_rating }}</button>
</div>
</div>
</div>
{% endfor %}
<script src="{% static 'ratings.js' %}"></script>
{% block script %}{% endblock %}
{% endblock %}
Также добавим в шаблон полной статьи новые изменения post_detail.html:
{% extends 'main.html' %}
{% load mptt_tags %}
{% load static %}
{% block content %}
<div class="card mb-3">
<div class="row">
<div class="col-4">
<img src="{{ post.thumbnail.url }}" class="card-img-top" alt="{{ post.title }}" />
</div>
<div class="col-8">
<div class="card-body">
<h5>{{ post.title }}</h5>
<p class="card-text">{{ post.description|safe }}</p>
<p class="card-text">{{ post.text|safe }}</p>
Категория: <a href="{% url 'post_by_category' post.category.slug %}">{{ post.category.title }}</a> / Добавил: {{ post.author.username }} / <small>{{ post.time_create }}</small>
</div>
</div>
</div>
{% if post.tags.all %}
<div class="card-footer border-0">
Теги записи: {% for tag in post.tags.all %} <a href="{% url 'post_by_tags' tag.slug %}">{{ tag }}</a>, {% endfor %}
</div>
{% endif %}
<div class="rating-buttons">
<button class="btn btn-sm btn-primary" data-post="{{ post.id }}" data-value="1">Лайк</button>
<button class="btn btn-sm btn-secondary" data-post="{{ post.id }}" data-value="-1">Дизлайк
</button>
<button class="btn btn-sm btn-secondary rating-sum">{{ post.get_sum_rating }}</button>
</div>
</div>
<div class="card border-0">
<div class="card-body">
<h5 class="card-title">
Комментарии
</h5>
{% include 'blog/comments/comments_list.html' %}
</div>
</div>
<script src="{% static 'ratings.js' %}"></script>
{% block script %}{% endblock %}
{% endblock %}
В следующем шаге мы проверим работу данной системы.