Создание сайта на Django: Урок 46, система подписчиков, часть 2 (JavaScript)
avatar
7 | (offline)
❤️‍🔥Notehunter Developer
Добавлено:
Категория: Руководства «Django»
Комментариев: 0

Если вы попали на эту страницу урока, не читая часть первую, то вам сюда: Создание сайта на Django: Урок 45, система подписчиков, часть 1 (представление, оформление)

Обновленная версия системы подписчиков

Создание кнопок для подписки на пользователя

В шаблоне profile-detail.html добавим сами кнопки, а также подключим JavaScript, создадим сам js файл позже.

templates/modules/system/profiles/profile-detail.html

{% extends 'main.html' %}
{% load static %}

{% block content %}
    <div class="card border-0 mb-2">
        <div class="card-body">
            <div class="row">
                <div class="col-md-3">
                    <figure>
                        <img src="{{ profile.get_avatar }}" class="img-fluid rounded-0" alt="{{ profile }}">
                    </figure>
                </div>
                <div class="col-md-9">
                     <h5 class="card-title">
                        {{ profile }}
                    </h5>
                    <div class="card-text">
                        <ul>
                            <li>Никнейм: {{ profile.user.username }}</li>
                            <li>Заходил: {{ profile.user.last_login }}</li>
                            <li>Возраст: {{ profile.get_age }}</li>
                            <li>О себе: {{ profile.bio }}</li>
                        </ul>
                        {% if request.user != profile.user and request.user.is_authenticated %}
                            {% if request.user.profile in profile.followers.all %}
                                <button class="btn btn-sm btn-danger btn-following" data-slug="{{ profile.slug }}">
                                    Отписаться от {{ profile }}
                                </button>
                            {% else %}
                               <button class="btn btn-sm btn-primary btn-following" data-slug="{{ profile.slug }}">
                                    Подписаться на {{ profile }}
                                </button>
                           {% endif %}
                        {% endif %}
                    </div>
                </div>
            </div>
        </div>
    </div>
    <div class="card border-0">
        <div class="card-body">
            <div class="row">
                <div class="col-md-6">
                    <h6 class="card-title">
                        Подписки
                    </h6>
                    <div class="card-text">
                     <div class="row">
                           {% for following in profile.following.all %}
                              <div class="col-md-2">
                               <a href="{{ following.get_absolute_url }}">
                                 <img src="{{ following.get_avatar }}" class="img-fluid rounded-1" alt="{{ following }}"/>
                               </a>
                              </div>
                          {% endfor %}
                     </div>
                    </div>
                </div>
                <div class="col-md-6">
                    <h6 class="card-title">
                        Подписчики
                    </h6>
                    <div class="card-text">
                        <div class="row" id="followersBox">
                           {% for follower in profile.followers.all %}
                              <div class="col-md-2" id="user-slug-{{ follower.slug }}">
                               <a href="{{ follower.get_absolute_url }}">
                                 <img src="{{ follower.get_avatar }}" class="img-fluid rounded-1" alt="{{ follower }}"/>
                               </a>
                              </div>
                          {% endfor %}
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
{% endblock %}

{% block script %}
    <script src="{% static 'custom/js/profile.js' %}"></script>
{% endblock %}

Пояснение:

  • Добавил {% block script %}<script src="{% static 'custom/js/profile.js' %}"></script>{% endblock %}
  • Добавил {% load static %} для подгрузки скрипта.
  • Добавил следующий фрагмент кода:
{% if request.user != profile.user and request.user.is_authenticated %}
                            {% if request.user.profile in profile.followers.all %}
                                <button class="btn btn-sm btn-danger btn-following" data-slug="{{ profile.slug }}">
                                    Отписаться от {{ profile }}
                                </button>
                            {% else %}
                               <button class="btn btn-sm btn-primary btn-following" data-slug="{{ profile.slug }}">
                                    Подписаться на {{ profile }}
                                </button>
                           {% endif %}
                        {% endif %}
  • Передаю в data-slug - ссылку пользователя.
  • В зависимости от того, на странице своего профиля находится пользователь, или же на странице другого пользователя - кнопки показываются соответствующие, либо отсутствуют. 

Теперь создадим в папке custom/js файл profile.js

templates/src/custom/js/profile.js

const subscribeBtn = document.querySelector('.btn-following')
const followerBox = document.querySelector('#followersBox')

subscribeBtn.addEventListener('click', subscribeUser)

function subscribeUser() {
    const subscribe = this;
    const subscribeProfileSlug = subscribe.getAttribute('data-slug');
    fetch(`/s/user/${subscribeProfileSlug}/follow/`, {
        method: 'POST',
            headers: {
                'X-CSRFToken': csrftoken,
                "X-Requested-With": "XMLHttpRequest",
            },
    }).then((response) => response.json()).then((result) => {
        if (subscribeBtn.classList.contains('btn-primary')) {
            subscribeBtn.classList.remove('btn-primary')
            subscribeBtn.classList.add('btn-danger')
        } else {
            subscribeBtn.classList.remove('btn-danger')
            subscribeBtn.classList.add('btn-primary')
        }
        if (result['error']) {
            subscribeBtn.innerText = `${result['error']}`
        } else {
            if (result['status']) {
                followerBox.innerHTML += `
                     <div class="col-md-2" id="user-slug-${result['following_slug']}">
                         <a href="${result['following_get_absolute_url']}">
                           <img src="${result['following_avatar']}" class="img-fluid rounded-1" alt="${result['following_slug']}"/>
                         </a>
                      </div>
                `
                subscribeBtn.innerHTML = `${result['message']}`
            }
            else {
                const currentSlugUser = document.querySelector(`#user-slug-${result['following_slug']}`)
                currentSlugUser.remove()
                subscribeBtn.innerHTML = `${result['message']}`
            }
        }
    })
}

Пояснение:

  • subscribeBtn - находим кнопку подписки по классу .btn-following
  • followerBox - находим блок подписчики, для добавления/удаления пользователя без перезагрузки страницы.
  • Добавляем к subscribeBtn событие клика, передаем функцию subscribeUser()
  • Создаем функцию subscribeUser(), получаем слаг профиля, а также создаем метод отправки POST запроса с помощью fetch
  • Преобразуем получаемый json в результат, разворачиваем в условиях, добавляем классы кнопкам, добавляем пользователя к подписчикам.

Примечание: я не очень хорошо разбираюсь в JavaScript, поэтому знатоки, можете его оптимизировать так, как вам нужно. Я ещё с JS много не практиковался.

Тестируем на сайте:

Кликаем по кнопке отписаться

Результат:

Снова нажимаем подписаться:

Отлично. Все работает так, как надо. Вы же можете оформить все это так, как хотите. Принцип знаете.

Комментарии к статье 0
Комментариев нет
Форма добавления комментария (необходима регистрация)