|
|
# FRR:该模块定义评论提交的视图类,负责处理用户提交评论的表单验证、
|
|
|
# 数据存储及页面跳转等逻辑,是评论功能与用户交互的核心处理层。
|
|
|
|
|
|
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 # 导入评论模型,用于存储评论数据
|
|
|
|
|
|
|
|
|
# FRR:评论提交视图类,继承FormView处理表单提交逻辑
|
|
|
class CommentPostView(FormView):
|
|
|
form_class = CommentForm # 指定使用的表单类为CommentForm
|
|
|
template_name = 'blog/article_detail.html' # 表单验证失败时渲染的模板(文章详情页)
|
|
|
|
|
|
# FRR:为视图方法添加CSRF保护装饰器,防止跨站请求伪造攻击
|
|
|
@method_decorator(csrf_protect)
|
|
|
def dispatch(self, *args, **kwargs):
|
|
|
# 调用父类的dispatch方法,确保视图正常处理请求
|
|
|
return super(CommentPostView, self).dispatch(*args, **kwargs)
|
|
|
|
|
|
# FRR:处理GET请求(直接访问评论提交URL时)
|
|
|
def get(self, request, *args, **kwargs):
|
|
|
article_id = self.kwargs['article_id'] # 从URL中获取文章ID
|
|
|
article = get_object_or_404(Article, pk=article_id) # 获取对应的文章,不存在则返回404
|
|
|
url = article.get_absolute_url() # 获取文章详情页的URL
|
|
|
# 重定向到文章详情页的评论区(#comments为评论区锚点)
|
|
|
return HttpResponseRedirect(url + "#comments")
|
|
|
|
|
|
# FRR:表单验证失败时的处理逻辑
|
|
|
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
|
|
|
})
|
|
|
|
|
|
# FRR:表单验证成功后的处理逻辑(核心方法)
|
|
|
def form_valid(self, form):
|
|
|
"""提交的数据验证合法后的逻辑"""
|
|
|
user = self.request.user # 获取当前登录用户
|
|
|
author = BlogUser.objects.get(pk=user.pk) # 获取用户对应的BlogUser实例
|
|
|
article_id = self.kwargs['article_id'] # 从URL获取文章ID
|
|
|
article = get_object_or_404(Article, pk=article_id) # 获取文章对象
|
|
|
|
|
|
# FRR:检查文章是否允许评论(状态为关闭则抛出验证异常)
|
|
|
if article.comment_status == 'c' or article.status == 'c':
|
|
|
raise ValidationError("该文章评论已关闭.")
|
|
|
|
|
|
# FRR:创建评论对象但不保存到数据库(save(False))
|
|
|
comment = form.save(False)
|
|
|
comment.article = article # 关联评论到当前文章
|
|
|
|
|
|
# FRR:根据网站设置决定评论是否需要审核(默认需要审核,is_enable=False)
|
|
|
from djangoblog.utils import get_blog_setting
|
|
|
settings = get_blog_setting() # 获取博客全局设置
|
|
|
if not settings.comment_need_review: # 若无需审核
|
|
|
comment.is_enable = True # 直接设为启用状态
|
|
|
|
|
|
comment.author = author # 关联评论作者为当前登录用户
|
|
|
|
|
|
# FRR:处理回复功能(若存在父评论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 # 关联到父评论
|
|
|
|
|
|
# FRR:保存评论到数据库(save(True)触发模型的save方法和信号)
|
|
|
comment.save(True)
|
|
|
|
|
|
# FRR:重定向到文章详情页的当前评论位置(锚点定位到具体评论)
|
|
|
return HttpResponseRedirect(
|
|
|
"%s#div-comment-%d" %
|
|
|
(article.get_absolute_url(), comment.pk)) |