Django 5 для начинающих

Прогресс по курсу:  9/1004

11.6 Создание системы Like / Dislike
3 из 3 шагов пройдено

Определим представление в 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 %}

В следующем шаге мы проверим работу данной системы.


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