# 赵瑞萍:评论提交视图模块,用于处理用户评论发布、数据验证、业务逻辑处理及响应返回 # 基于Django FormView实现,支持CSRF保护、表单验证、评论状态控制及回复功能处理 # 赵瑞萍:导入Django核心组件,提供异常处理、响应、数据查询及装饰器支持 from django.core.exceptions import ValidationError # 数据验证异常,用于抛出评论相关业务错误 from django.http import HttpResponseRedirect # 重定向响应类,用于评论成功后跳转 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 # 自定义用户模型,用于关联评论作者 from blog.models import Article # 文章模型,评论需关联具体文章 from .forms import CommentForm # 评论表单,用于前端输入验证 from .models import Comment # 评论模型,用于数据存储 class CommentPostView(FormView): """ 赵瑞萍:评论提交处理类视图,继承FormView封装表单处理流程 核心功能:接收评论提交请求、验证数据合法性、处理评论保存逻辑、返回对应响应 支持场景:普通评论发布、评论回复、评论审核状态控制、CSRF防护 """ # 赵瑞萍:指定表单类为CommentForm,用于数据验证和字段映射 form_class = CommentForm # 赵瑞萍:指定模板为文章详情页,用于表单错误时重新渲染页面并显示错误 template_name = 'blog/article_detail.html' @method_decorator(csrf_protect) def dispatch(self, *args, **kwargs): """ 赵瑞萍:重写dispatch方法,添加CSRF保护 通过method_decorator将csrf_protect装饰器应用到请求分发流程,确保所有请求经过CSRF验证 防止跨站请求伪造攻击,保护评论提交接口安全 """ # 赵瑞萍:调用父类dispatch方法,维持原有请求分发逻辑 return super(CommentPostView, self).dispatch(*args, **kwargs) def get(self, request, *args, **kwargs): """ 赵瑞萍:处理GET请求,避免直接通过URL访问评论提交接口 当用户以GET方式访问时,重定向到对应文章详情页的评论区 """ # 赵瑞萍:从URL参数中获取文章ID,确定评论所属文章 article_id = self.kwargs['article_id'] # 赵瑞萍:查询文章对象,不存在则返回404 article = get_object_or_404(Article, pk=article_id) # 赵瑞萍:获取文章绝对URL,拼接评论区锚点,重定向到评论区 url = article.get_absolute_url() return HttpResponseRedirect(url + "#comments") def form_invalid(self, form): """ 赵瑞萍:表单数据验证失败时的处理方法 当用户输入不符合规则(如评论为空、长度超限),重新渲染文章详情页并携带错误信息 """ # 赵瑞萍:从URL参数获取文章ID,关联当前评论的文章 article_id = self.kwargs['article_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 # 赵瑞萍:根据用户ID查询BlogUser实例,作为评论作者 author = BlogUser.objects.get(pk=user.pk) # 赵瑞萍:从URL参数获取文章ID,确定评论所属文章 article_id = self.kwargs['article_id'] # 赵瑞萍:查询文章对象,不存在则返回404 article = get_object_or_404(Article, pk=article_id) # 赵瑞萍:业务规则校验——检查文章是否允许评论 # 若文章评论状态为'c'(关闭)或文章状态为'c'(关闭),抛出验证异常 if article.comment_status == 'c' or article.status == 'c': raise ValidationError("该文章评论已关闭.") # 赵瑞萍:保存表单数据但不提交到数据库(commit=False),预留字段补充空间 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']: # 赵瑞萍:根据父评论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和评论锚点(如#div-comment-1) )