Создание представления для добавления комментария через 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 код для добавления комментариев без перезагрузки страницы.