You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
DjangoBlog/comments/views.py

115 lines
6.3 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 赵瑞萍:评论提交视图模块,用于处理用户评论发布、数据验证、业务逻辑处理及响应返回
# 基于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
)