# Create your views here. from django.core.exceptions import ValidationError # 导入验证异常类,用于处理验证错误 from django.http import HttpResponseRedirect # 导入HTTP重定向类,用于页面跳转 from django.shortcuts import get_object_or_404 # 导入获取对象或返回404的工具函数 from django.utils.decorators import method_decorator # 导入方法装饰器工具,用于为类视图方法添加装饰器 from django.views.decorators.csrf import csrf_protect # 导入CSRF保护装饰器,防止跨站请求伪造 from django.views.generic.edit import FormView # 导入表单视图基类,用于处理表单提交逻辑 from accounts.models import BlogUser # 从accounts应用导入用户模型 from blog.models import Article # 从blog应用导入文章模型 from .forms import CommentForm # 从当前应用导入评论表单 from .models import Comment # 从当前应用导入评论模型 class CommentPostView(FormView): """评论提交视图类,处理评论发布功能""" form_class = CommentForm # 指定使用的表单类为CommentForm template_name = 'blog/article_detail.html' # 指定表单验证失败时渲染的模板 @method_decorator(csrf_protect) # 为dispatch方法添加CSRF保护 def dispatch(self, *args, **kwargs): # 调用父类的dispatch方法,处理请求分发 return super(CommentPostView, self).dispatch(*args, **kwargs) def get(self, request, *args, **kwargs): """处理GET请求:重定向到文章详情页的评论区""" article_id = self.kwargs['article_id'] # 从URL参数中获取文章ID article = get_object_or_404(Article, pk=article_id) # 获取对应的文章对象,不存在则返回404 url = article.get_absolute_url() # 获取文章的绝对URL return HttpResponseRedirect(url + "#comments") # 重定向到文章详情页的评论区锚点 def form_invalid(self, form): """处理表单验证失败的情况""" article_id = self.kwargs['article_id'] # 获取文章ID article = get_object_or_404(Article, pk=article_id) # 获取文章对象 # 渲染文章详情页,传递错误的表单和文章对象(用于显示错误信息) return self.render_to_response({ 'form': form, # 验证失败的表单(包含错误信息) 'article': article # 文章对象 }) def form_valid(self, form): """处理表单验证通过后的逻辑:保存评论并跳转""" user = self.request.user # 获取当前登录用户 author = BlogUser.objects.get(pk=user.pk) # 获取用户对应的BlogUser对象 article_id = self.kwargs['article_id'] # 获取文章ID article = get_object_or_404(Article, pk=article_id) # 获取文章对象 # 检查文章是否允许评论(评论状态为关闭或文章状态为草稿则不允许评论) if article.comment_status == 'c' or article.status == 'c': raise ValidationError("该文章评论已关闭.") # 抛出验证异常 comment = form.save(False) # 不立即保存表单数据,返回评论对象 comment.article = article # 设置评论关联的文章 # 获取博客设置,判断评论是否需要审核 from djangoblog.utils import get_blog_setting settings = get_blog_setting() if not settings.comment_need_review: # 如果不需要审核 comment.is_enable = True # 直接设置评论为启用状态 comment.author = author # 设置评论的作者 # 处理回复功能:如果存在父评论ID,则设置父评论 if form.cleaned_data['parent_comment_id']: parent_comment = Comment.objects.get( pk=form.cleaned_data['parent_comment_id']) # 获取父评论对象 comment.parent_comment = parent_comment # 设置当前评论的父评论 comment.save(True) # 保存评论到数据库 # 重定向到文章详情页的当前评论位置(带锚点) return HttpResponseRedirect( "%s#div-comment-%d" % (article.get_absolute_url(), comment.pk)) # 拼接URL,包含评论ID锚点