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

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

11.1 Создание древовидных комментариев
2 из 2 шагов пройдено

Создание представления для добавления комментария через JS

Теперь создадим представление для добавления комментариев с помощью JavaScript, для этого в файл views.py приложения blog добавьте следующий код:

from django.http import JsonResponse
from django.shortcuts import redirect
from .forms import CommentCreateForm
from .models import Comment


class CommentCreateView(LoginRequiredMixin, CreateView):
    model = Comment
    form_class = CommentCreateForm

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

    def form_invalid(self, form):
        if self.is_ajax():
            return JsonResponse({'error': form.errors}, status=400)
        return super().form_invalid(form)

    def form_valid(self, form):
        comment = form.save(commit=False)
        comment.post_id = self.kwargs.get('pk')
        comment.author = self.request.user
        comment.parent_id = form.cleaned_data.get('parent')
        comment.save()

        if self.is_ajax():
            return JsonResponse({
                'is_child': comment.is_child_node(),
                'id': comment.id,
                'author': comment.author.username,
                'parent_id': comment.parent_id,
                'time_create': comment.time_create.strftime('%Y-%b-%d %H:%M:%S'),
                'avatar': comment.author.profile.avatar.url,
                'content': comment.content,
                'get_absolute_url': comment.author.profile.get_absolute_url()
            }, status=200)

        return redirect(comment.post.get_absolute_url())

    def handle_no_permission(self):
        return JsonResponse({'error': 'Необходимо авторизоваться для добавления комментариев'}, status=400)

Это представление на основе класса CreateView, которое позволяет обрабатывать форму создания комментария в AJAX.

Мы используем миксин LoginRequiredMixin, что гарантирует, что только авторизованный пользователь может создать комментарий.

Метод is_ajax() возвращает True, если запрос был сделан через AJAX, и False в противном случае.

Метод form_invalid() вызывается, когда форма создания комментария не проходит валидацию. Если запрос был через AJAX, то возвращается JsonResponse с ошибкой, иначе вызывается родительский метод form_invalid().

Метод form_valid() вызывается, когда форма создания комментария прошла валидацию. В нем сохраняется новый комментарий, и возвращается успешный ответ с атрибутами в виде json с помощью JsonResponse, в случае, если это был не AJAX запрос, то делаем редирект пользователя на статью.


Далее нам необходимо модернизировать представление вывода детальной статьи:

class PostDetailView(DetailView):
    model = Post
    template_name = 'blog/post_detail.html'
    context_object_name = 'post'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['title'] = self.object.title
        context['form'] = CommentCreateForm  # new
        return context

Мы добавили в вывод нашей формы в шаблон, используя переменную {{ form }}.


Теперь осталось добавить комментарии в админ-панель и добавить обработку представления в urls.py. Для этого в файл urls.py приложения blog добавим следующую строку:

from django.urls import path
from .views import PostListView, PostDetailView, PostFromCategory, PostCreateView, PostUpdateView, CommentCreateView

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'), # New
    path('category/<str:slug>/', PostFromCategory.as_view(), name="post_by_category"),

]


Добавим модели комментариев в админ-панель, для этого в файле admin.py нашего приложения blog добавляем следующий код:

from .models import Comment

@admin.register(Comment)
class CommentAdminPage(DjangoMpttAdmin):
    """
    Админ-панель модели комментариев
    """
    pass


В следующем разделе мы добавим всё это в шаблон и добавим JavaScript код для добавления комментариев без перезагрузки страницы.


Будьте вежливы и соблюдайте наши принципы сообщества. Пожалуйста, не оставляйте решения и подсказки в комментариях, для этого есть отдельный форум.
Оставить комментарий
def form_valid(self, form):
        comment = form.save(commit=False)
        comment.post_id = self.kwargs.get('pk')
        comment.author = self.request.user
        comment.parent_id = form.cleaned_data.get('parent')
        comment.save()

В предыдущем разделе поля назывались post и  parent без id

@Аскер_Молов, Разобрался, comment.post_id  это способ обратиться к полю с внешним ключом на post в таблице comment