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

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

Вывод подписчиков в шаблоне Django

Напоминаю, что в проекте я использую декомпозицию.

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

Мы добавили следующее поле к профилю пользователя: following = models.ManyToManyField('self', verbose_name='Подписки', related_name='followers', symmetrical=False, blank=True)

Пояснения:

  • Это поле многое ко многим (m2m).
  • related_name задал как followers
  • symmetrical - отвечает за то, чтоб подписка происходила в одностороннем порядке.

Давайте добавим вывод в шаблон подписчиков, а также добавим их через админку.

Создам пару профилей, и подпишусь с моего аккаунта на них:

А теперь перейду в шаблон профиля и добавлю следующие шаблонные теги для вывода подписчиков:

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

{% extends 'main.html' %}

{% 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>

                    </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 %}

Пояснения:

  • Я добавил вывод подписчиков и подписки на других пользователей
  • id followersBox понадобится для javascript.
  • Передавать мы будем slug для JS

Как это выглядит на сайте:

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

В представления профиля добавлю следующий фрагмент кода:

modules/system/views/profiles.py

from django.views import View
from django.http import JsonResponse


class ProfileFollowingCreateView(View):
    """
    Создание подписки для пользователей
    """
    model = Profile

    def is_ajax(self):
        return self.request.headers.get('X-Requested-With') == 'XMLHttpRequest'

    def post(self, request, slug):
        if self.is_ajax():
            user = self.model.objects.get(slug=slug)
            current_user = request.user
            if current_user.is_authenticated:
                profile = current_user.profile
                if profile in user.followers.all():
                    user.followers.remove(profile)
                    return JsonResponse({
                        'author': current_user.username,
                        'following_avatar': profile.get_avatar,
                        'following_get_absolute_url': profile.get_absolute_url(),
                        'following_slug': profile.slug,
                        'message': f'Подписаться на {user}',
                        'status': False},
                    status=200)
                else:
                    user.followers.add(profile)
                    return JsonResponse({
                        'author': current_user.username,
                        'following_get_absolute_url': profile.get_absolute_url(),
                        'following_slug': profile.slug,
                        'following_avatar': profile.get_avatar,
                        'message': f'Отписаться от {user}',
                        'status': True},
                        status=200)
            else:
                return JsonResponse({'error': 'Необходима авторизация на сайте'}, status=400)

Пояснения:

  • Это представление будет работать только в JS.
  • Логика довольно проста, если текущего пользователя нет в подписка пользователя, он добавляется, иначе - удаляется. 
  • Передаем данные после выполнения в JsonResponse.

Добавим наше представление в urls.py

modules/system/urls.py

from django.urls import path

from modules.system.views import ProfileView, ProfileEditView, RegisterCreateView, UserLoginView, \
    UserPasswordChangeView, UserForgotPasswordView, UserPasswordResetConfirmView, UserLogoutView, ActivateAccountView, \
    FeedbackCreateView, ProfileFollowingCreateView

urlpatterns = [
    path('user/edit/', ProfileEditView.as_view(), name='profile-edit'),
    path('user/<str:slug>/', ProfileView.as_view(), name='profile'),
    path('user/<str:slug>/follow/', ProfileFollowingCreateView.as_view(), name='follow-to-user'),
    path('register/', RegisterCreateView.as_view(), name='register'),
    path('login/', UserLoginView.as_view(), name='login'),
    path('logout/', UserLogoutView.as_view(), name='logout'),
    path('password-change/', UserPasswordChangeView.as_view(), name='password-change'),
    path('password-reset/', UserForgotPasswordView.as_view(), name='password-reset'),
    path('set-new-password/<uidb64>/<token>/', UserPasswordResetConfirmView.as_view(), name='password-reset-confirm'),
    path('activate/<uidb64>/<token>/', ActivateAccountView.as_view(), name='activate'),
    path('feedback/', FeedbackCreateView.as_view(), name='feedback-create-view'),
]

На этом урок закончен, в следующем уроке мы уже просто оформим работу системы подписок через JavaScript, добавив необходимые кнопки. 

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